Java中如何反转int数组?

295

我正在尝试在Java中反转一个int数组。

该方法无法反转数组。

for(int i = 0; i < validData.length; i++)
{
    int temp = validData[i];
    validData[i] = validData[validData.length - i - 1];
    validData[validData.length - i - 1] = temp;
}

它有什么问题?


39
我明白我哪里做错了。应该是validData.length/2才对。否则它会反转然后再次反转回来。 - MichaelScott
4
请参阅 http://en.wikipedia.org/wiki/In-place_algorithm,其中包含该算法的正确版本描述。 - Dean Povey
Java 8: https://dev59.com/KnI95IYBdhLWcg3w1BhN#46756353 - akhil_mittal
48个回答

6

如果处理的数据比较原始(例如char,byte,int等),那么您可以执行一些有趣的XOR操作。

public static void reverseArray4(int[] array) {
    int len = array.length;
    for (int i = 0; i < len/2; i++) {
        array[i] = array[i] ^ array[len - i  - 1];
        array[len - i  - 1] = array[i] ^ array[len - i  - 1];
        array[i] = array[i] ^ array[len - i  - 1];
    }
}

这肯定会让你的代码读者感到困惑。 - Paŭlo Ebermann

6
这是我个人的解决方法。创建参数化方法的原因是允许对任何数组进行排序...不仅限于整数。
希望你从中获得一些收获。
@Test
public void reverseTest(){
   Integer[] ints = { 1, 2, 3, 4 };
   Integer[] reversedInts = reverse(ints);

   assert ints[0].equals(reversedInts[3]);
   assert ints[1].equals(reversedInts[2]);
   assert ints[2].equals(reversedInts[1]);
   assert ints[3].equals(reversedInts[0]);

   reverseInPlace(reversedInts);
   assert ints[0].equals(reversedInts[0]);
}

@SuppressWarnings("unchecked")
private static <T> T[] reverse(T[] array) {
    if (array == null) {
        return (T[]) new ArrayList<T>().toArray();
    }
    List<T> copyOfArray = Arrays.asList(Arrays.copyOf(array, array.length));
    Collections.reverse(copyOfArray);
    return copyOfArray.toArray(array);
}

private static <T> T[] reverseInPlace(T[] array) {
    if(array == null) {
        // didn't want two unchecked suppressions
        return reverse(array);
    }

    Collections.reverse(Arrays.asList(array));
    return array;
}

2
未使用基本单元解决原始问题。 - Melinda Green
有很多方法可以将prims转换为对象。我总是建议在Java中尽可能避免使用prims,我也认为应该鼓励这样做。 - AnthonyJClink
将长度未知的原始类型数组转换为数组可能是一个非常糟糕的想法,特别是如果不自知地这样做。Java不是Smalltalk。原始类型是语言的一部分,并且有其应用场景。无论我们是否喜欢它们,我们必须接受它们,并在适当的地方使用它们。 - Melinda Green
2
实际上您不需要复制数组,只需使用Collections.reverse(asList(arraytoReverse)); return arrayToReverse;asList只是一个数组的包装器,因此原始数组被反转。 - Radiodef
你的 return (T[]) new ArrayList<T>().toArray(); 实际上会返回一个空的 Object[],而不是参数所指定的类型。 - Paŭlo Ebermann

6

这将对你有所帮助

int a[] = {1,2,3,4,5};
for (int k = 0; k < a.length/2; k++) {
    int temp = a[k];
    a[k] = a[a.length-(1+k)];
    a[a.length-(1+k)] = temp;
}

4

这个问题有两种解决方案:

1. 原地反转数组。

步骤1:交换开头和结尾索引处的元素。

步骤2:增加起始索引,减少结束索引。

步骤3:重复执行步骤1和步骤2,直到起始索引 < 结束索引。

使用这种方法,时间复杂度为O(n),空间复杂度为O(1)。

原地反转数组的示例代码如下:

public static int[] reverseAnArrayInSpace(int[] array) {
    int startIndex = 0;
    int endIndex = array.length - 1;
    while(startIndex < endIndex) {
        int temp = array[endIndex];
        array[endIndex] = array[startIndex];
        array[startIndex] = temp;
        startIndex++;
        endIndex--;
    }
    return array;
}

2. 使用辅助数组来反转一个数组。

步骤1. 创建一个大小等于给定数组的新数组。

步骤2. 从给定数组的末尾索引开始,将元素插入到新数组的起始索引处。

这样做的时间复杂度为O(n),空间复杂度为O(n)。

使用辅助数组反转一个数组的示例代码如下:

public static int[] reverseAnArrayWithAuxiliaryArray(int[] array) {
    int[] reversedArray = new int[array.length];
    for(int index = 0; index < array.length; index++) {
        reversedArray[index] = array[array.length - index -1]; 
    }
    return reversedArray;
}

此外,我们可以使用Java中的Collections API来完成这个操作。

Collections API内部也使用相同的反向空间方法。

使用Collections API的示例代码如下:

public static Integer[] reverseAnArrayWithCollections(Integer[] array) {
    List<Integer> arrayList = Arrays.asList(array);
    Collections.reverse(arrayList);
    return arrayList.toArray(array);
}

4

你的程序只能处理length = 0, 1的情况。你可以尝试:

int i = 0, j = validData.length-1 ; 
while(i < j)
{
     swap(validData, i++, j--);  // code for swap not shown, but easy enough
}

3
也许你是想用内联交换的伪代码而不是方法调用来进行交换,但如果不是这样的话那是行不通的。Java按引用传递参数,所以不可能为变量编写交换方法。 - Dean Povey
我是指任何可以让 v[i] 和 v[j] 交换的方式。我知道 Java 中如何调用方法。对于方法,您可以像这样做:swap(v,i ++,j--); - fastcodejava
1
Dean,数组validData是一个通过引用传递的对象,因此swap()方法将完美地工作。 - Gaël Oberson

4

以上有很好的答案,但这是我做的方法:

public static int[] test(int[] arr) {

    int[] output = arr.clone();
    for (int i = arr.length - 1; i > -1; i--) {
        output[i] = arr[arr.length - i - 1];
    }
    return output;
}

3
public void getDSCSort(int[] data){
        for (int left = 0, right = data.length - 1; left < right; left++, right--){
            // swap the values at the left and right indices
            int temp = data[left];
            data[left]  = data[right];
            data[right] = temp;
        }
    }

3

使用 O(n) 时间复杂度和 O(1) 空间复杂度的解决方案。

void reverse(int[] array) {
    int start = 0;
    int end = array.length - 1;
    while (start < end) {
        int temp = array[start];
        array[start] = array[end];
        array[end] = temp;
        start++;
        end--;
    }
}

只是提供信息,这可以简化为一个复杂的for循环:for (int start = 0, end = array.length - 1; start < end; start++, end--) { ... } - Tim Cooke

3

迭代数组时,最高效的方法是从后往前迭代。

我不确定Aaron的解决方案是否通过此调用实现 Collections.reverse(list);。有人知道吗?


逆向迭代数组需要一个新的数组。我喜欢上面发布的解决方案,它可以在不创建新数组的情况下进行内联反转。 - mmcdole
1
@Simucal 为什么要创建一个新数组?只需反向迭代即可。 - Hakanai

2
使用异或解决方案来避免使用临时变量,你的代码应该如下所示:
for(int i = 0; i < validData.length; i++){
    validData[i] = validData[i] ^ validData[validData.length - i - 1];
    validData[validData.length - i - 1] = validData[i] ^ validData[validData.length - i - 1];
    validData[i] = validData[i] ^ validData[validData.length - i - 1];
}

请查看以下链接以获得更好的解释: http://betterexplained.com/articles/swap-two-variables-using-xor/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接