如何在Java中反转int数组?


238

我正在尝试反转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;
}

怎么了


31
我明白我做错了。应该是validData.length / 2。否则,它将反转自身,然后反转自身。
MichaelScott 2010年

4
请参阅en.wikipedia.org/wiki/In-place_algorithm,其中包含对该算法的正确版本的描述。
Dean Povey 2010年

Answers:


283

要反转一个int数组,可以交换项直到达到中点为止,如下所示:

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

这样,您将每个元素交换两次,因此结果与初始列表相同。


我想将validData.length / 2一部分放在for循环之外。
晋权2014年

7
@Jin我不会。它只会混淆含义,我敢打赌,优化编译器无论如何都会为您完成。无论如何,只有从剖析中获得明确的证据表明它是必要/有帮助的,微优化才有意义。
Nicu Stiurca 2014年

9
@JinKwon有点像在做validData.length >> 1。那是等效的并且更快,但是它使许多程序员感到困惑,任何好的编译器都会自动这样做。
贾斯汀

2
您只应执行一次此计算validData.length - i - 1并将其保存到变量。

谁能建议一个没有临时变量的逆转!
sg28 '18年

303

使用Commons.Lang,您可以简单地使用

ArrayUtils.reverse(int[] array)

在大多数情况下,坚持使用已经过单元测试和用户测试的易于使用的库来解决问题时,这种方法更加快捷,更加安全。


3
我本来希望它返回类似功能的样式的反向(传递)数组。
Laurent G

2
@ laurent-g是公平的:以这种方式反转数组的内存效率更高,这可能就是他们这样做的原因。
Sirmyself

4
我的意思不是复制还是不复制。我的消息指出要返回“(通过)”(反转后),因此可以在表达式中传递它,而无需单独的语句。
洛朗G

52
public class ArrayHandle {
    public static Object[] reverse(Object[] arr) {
        List<Object> list = Arrays.asList(arr);
        Collections.reverse(list);
        return list.toArray();
    }
}

11
当然会。列表只能包含对象,而不能包含基元,因此所有基元(int在这种情况下为s)都被包装到其各自的包装器(Integer在这种情况下为s)并放入列表中。您会看到Integers是对象。@Tom
1684年

6
注意:如果我没记错的话,原始数组会被修改。为了清楚起见,您可能只想不返回任何东西。
Andrea Zilio

3
@ 11684是的,泛型列表只能容纳对象。但是该方法除外一个数组。数组可以保存原语。因此int[]不同于Integer[]。试试看:Integer[] array = new int[5]。您会得到一个编译错误。这就是Java Arrays类定义一堆用于基本数组的方法的原因。尝试将传递int[]给上述方法会导致类似的情况The method reverse(Object[]) in the type MakeSimple is not applicable for the arguments (int[])。@Filip-就地算法使用更少的内存并运行得更快。
Brian McCutchon 2014年

3
@Andrea其实不是。返回的列表Arrays.asList()不引用原始数组,也不返回该数组。这是此方法的问题之一:作为就地算法,它使用三倍的内存并将三倍的工作量。
Brian McCutchon 2014年

4
此方法本身可能会起作用,但是不能将a int[]作为参数传递给此方法(“不兼容的类型:int []无法转换为Object []”)。
MC Emperor

47
Collections.reverse(Arrays.asList(yourArray));

java.util.Collections.reverse()可以反转java.util.Lists并java.util.Arrays.asList()返回一个列表,该列表包装您传递给它的特定数组,因此yourArray在调用之后被反转Collections.reverse()

成本只是创建一个List对象,而无需其他库。

Tarik及其评论者的答案中也提出了类似的解决方案,但我认为此答案将更简洁,更易于解析。


14
对于对象数组,这是一个很好的解决方案。但这不适用于原始数组。例如 传递一个int[]to asList(...)将不会返回包含一个元素的List<Integer>,而是一个List<int[]>。没有AFAICS没有简单的内置方法将转换int[]Integer[]
马丁·鲁斯特

4
这将不适用于原始数组...集合dosnt返回一个值,因此现在您有了一个无用的数组作为内存中的列表
NightSkyCode

@MartinRust Java 8+:Arrays.stream(arr).boxed().collect(Collectors.toList())Arrays.stream(arr).boxed().toArray(Integer[]::new)
Simon Forsberg

39

我认为,如果您声明显式变量来跟踪每次循环迭代时要交换的索引,则遵循算法的逻辑会容易一些。

public static void reverse(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;
    }
}

我还认为在while循环中执行此操作更具可读性。

public static void reverse(int[] data) {
    int left = 0;
    int right = data.length - 1;

    while( left < right ) {
        // swap the values at the left and right indices
        int temp = data[left];
        data[left] = data[right];
        data[right] = temp;

        // move the left and right index pointers in toward the center
        left++;
        right--;
    }
}

老式的交换看起来更容易,但是可以,当涉及数组索引值left,right,...时,将有助于调试
Srinath Ganesh 2014年

您还可以添加'public static void swap(int [] data,int index1,int index2){...}'并像这样从'reverse'中使用它:swap(data,left,right)。
pm_ 2015年

13

这里已经有很多答案,主要集中在就地修改数组。但是出于完整性考虑,以下是使用Java流保留原始数组并创建新的反向数组的另一种方法:

    int[] a = {8, 6, 7, 5, 3, 0, 9};
    int[] b = IntStream.rangeClosed(1, a.length).map(i -> a[a.length-i]).toArray();

10

用番石榴:

Collections.reverse(Ints.asList(array));

4
这太棒了!简短有效。与所有asList方法一样,它创建一个视图,该视图直接写入后备(原始)数组。我认为这里的选民错误地认为这返回了装箱清单或其他内容。
路加·乌瑟伍德

@LukeUsherwood大概在每个元素上调用get和set时,装箱和拆箱仍然会有一些开销。但是我同意你的看法,这是一个绝妙的解决方案。
帕特里克·帕克

确实,这是值得注意的。我认为在我个人使用的大多数代码中没什么大不了的-我们的“热门”领域定义明确,其余的都是“胶水代码”。同时,我意识到内存流失还会产生额外的“隐藏”成本,而探查器无法将其归因于实际功能。
路加·厄舍伍德

@LukeUsherwood它仍然返回盒装列表,而不是原始数组
AnthonyJClink '18

2
@AnthonyJClink不确定“ it”指的是什么,但是JDK实用程序Collections.reverse是一个无效方法。这在包装了的Guava内部类上就地操作int[](因为它从不存储Boxed的列表,Integer所以我不称该类为“ Boxed列表”,而是“数组的List视图”)。但是,是的,它通过传递Integer对象的接口进行操作,因此,如上所述,这将导致大量临时对象搅动和装箱。IntStream在性能很重要的地方尝试使用一个或原始集合库。(Trove,Koloboke,Eclipse Collections,...)
Luke Usherwood

9

Java 8的情况下,我们还可以IntStream将整数数组反转为:

int[] sample = new int[]{1,2,3,4,5};
int size = sample.length;
int[] reverseSample = IntStream.range(0,size).map(i -> sample[size-i-1])
                      .toArray(); //Output: [5, 4, 3, 2, 1]



5
for(int i=validData.length-1; i>=0; i--){
  System.out.println(validData[i]);
 }

不幸的是,这是这里最干净的答案,因为每个开发人员都知道如何做,并且不需要安装任何扩展的软件包。
HoldOffHunger

4

这就是我个人解决的方法。创建参数化方法的原因是允许对任何数组进行排序……而不仅仅是您的整数。

我希望你从中收集到一些东西。

@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
不能使用原始函数解决原始问题。
梅琳达·格林

有很多方法可以将素数转换为对象。我总是建议在Java中尽可能避免使用prims,并且我也应该鼓励这样做。
AnthonyJClink

将未知长度的图元数组转换成数组可能是一个非常糟糕的主意,尤其是在没有意识到的情况下。Java不是Smalltalk。原始语言是语言的一部分,并且有其地位。我们是否不喜欢它们并不重要,我们必须接受它们,并在适当的地方使用它们。
梅琳达·格林

1
实际上,您实际上不需要复制数组Collections.reverse(asList(arraytoReverse)); return arrayToReverse;asList只是数组的包装,因此原始数组被颠倒了。
Radiodef 2015年

3

您的程序仅适用于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 2010年

我的意思是您可以通过任何方式交换v [i]和v [j]。我知道方法调用在Java中是如何工作的。对于方法,您可以执行诸如swap(v,i ++,j--);之类的操作。
fastcodejava

1
教务长,数组validData是一个对象,通过引用传递,因此swap()方法将完美工作。
盖尔·奥伯森(GaëlOberson)2015年

3

如果使用更原始的数据(即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];
    }
}

1
太可爱了,无法在生产代码中实际使用,但仍然很有趣。对于最大可爱,使用%=操作是这样的:阵列[I](%)=阵列[len个- I - 1],等等
梅林达格林

类似,但短一些:for (int m = x.length, i = --m / 2; ++i <= m;) { x[i] ^= x[m - i]; x[i] ^= x[m - i] ^= x[i]; }
Thomas Mueller

2

简单地向后迭代数组是最有效的。

我不确定亚伦的解决方案Collections.reverse(list);是否可以通过此电话进行通话,有人知道吗?


向后迭代数组需要一个新的数组。我喜欢上面发布的解决方案,该解决方案无需创建新数组即可进行内联反转。
mmcdole 2010年

1
@Simucal为什么要创建一个新数组?只是向后迭代。
Trejkaz

2
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;
        }
    }

1
public void display(){
  String x[]=new String [5];
  for(int i = 4 ; i > = 0 ; i-- ){//runs backwards

    //i is the nums running backwards therefore its printing from       
    //highest element to the lowest(ie the back of the array to the front) as i decrements

    System.out.println(x[i]);
  }
}

1
是的,我尝试了相同且清晰的代码以及输出,它是int [] a = {1,3,5,2,6,7}; for(int i = a.length-1; i> = 0; i--){System.out.print(a [i] +“”);}`它将把数组从最后一个索引转换为第一个索引
Rocket_03 '18

1

难道不是这样会出错吗?

    int[] intArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int[] temp = new int[intArray.length];
    for(int i = intArray.length - 1; i > -1; i --){
            temp[intArray.length - i -1] = intArray[i];
    }
    intArray = temp;

1

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--) { ... }
蒂姆·库克

1

反转Array的2种方法。

  1. 使用For循环并以O(n / 2)的时间复杂度交换元素直到中点。

    private static void reverseArray() {
    int[] array = new int[] { 1, 2, 3, 4, 5, 6 };
    
    for (int i = 0; i < array.length / 2; i++) {
        int temp = array[i];
        int index = array.length - i - 1;
        array[i] = array[index];
        array[index] = temp;
    }
    System.out.println(Arrays.toString(array));

    }

  2. 使用内置函数(Collections.reverse())

    private static void reverseArrayUsingBuiltInFun() {
    int[] array = new int[] { 1, 2, 3, 4, 5, 6 };
    
    Collections.reverse(Ints.asList(array));
    System.out.println(Arrays.toString(array));

    }

    输出:[6、5、4、3、2、1]


3
什么Ints
CodingNow19年

@CodingNow这是番石榴实用的辅助类之一-看这里
MREC

0

以下是要在您的计算机上运行的完整程序。

public class ReverseArray {
    public static void main(String[] args) {
        int arr[] = new int[] { 10,20,30,50,70 };
        System.out.println("reversing an array:");
        for(int i = 0; i < arr.length / 2; i++){
            int temp = arr[i];
            arr[i] = arr[arr.length - i - 1];
            arr[arr.length - i - 1] = temp;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }   
    }
}

对于使用数组在矩阵上的程序,这将是一个很好的来源


0

使用XOR解决方案来避免temp变量,您的代码应该看起来像

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/


0
private static int[] reverse(int[] array){
    int[] reversedArray = new int[array.length];
    for(int i = 0; i < array.length; i++){
        reversedArray[i] = array[array.length - i - 1];
    }
    return reversedArray;
} 

4
请考虑在回答中添加说明。仅代码的答案什么也不能解释。
rgettman 2014年

0

这是一个简单的实现,可以反转任何类型的数组,以及全部/部分支持。

import java.util.logging.Logger;

public final class ArrayReverser {
 private static final Logger LOGGER = Logger.getLogger(ArrayReverser.class.getName());

 private ArrayReverser () {

 }

 public static <T> void reverse(T[] seed) {
    reverse(seed, 0, seed.length);
 }

 public static <T> void reverse(T[] seed, int startIndexInclusive, int endIndexExclusive) {
    if (seed == null || seed.length == 0) {
        LOGGER.warning("Nothing to rotate");
    }
    int start = startIndexInclusive < 0 ? 0 : startIndexInclusive;
    int end = Math.min(seed.length, endIndexExclusive) - 1;
    while (start < end) {
        swap(seed, start, end);
        start++;
        end--;
    }
}

 private static <T> void swap(T[] seed, int start, int end) {
    T temp =  seed[start];
    seed[start] = seed[end];
    seed[end] = temp;
 }  

}

这是相应的单元测试

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import org.junit.Before;
import org.junit.Test;

public class ArrayReverserTest {
private Integer[] seed;

@Before
public void doBeforeEachTestCase() {
    this.seed = new Integer[]{1,2,3,4,5,6,7,8};
}

@Test
public void wholeArrayReverse() {
    ArrayReverser.<Integer>reverse(seed);
    assertThat(seed[0], is(8));
}

 @Test
 public void partialArrayReverse() {
    ArrayReverser.<Integer>reverse(seed, 1, 5);
    assertThat(seed[1], is(5));
 }
}

0

这是我想出的:

// solution 1 - boiler plated 
Integer[] original = {100, 200, 300, 400};
Integer[] reverse = new Integer[original.length];

int lastIdx = original.length -1;
int startIdx = 0;

for (int endIdx = lastIdx; endIdx >= 0; endIdx--, startIdx++)
   reverse[startIdx] = original[endIdx];

System.out.printf("reverse form: %s", Arrays.toString(reverse));

// solution 2 - abstracted 
// convert to list then use Collections static reverse()
List<Integer> l = Arrays.asList(original);
Collections.reverse(l);
System.out.printf("reverse form: %s", l);

0

有两种方法可以解决此问题:

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);
}

0
static int[] reverseArray(int[] a) {
     int ret[] = new int[a.length];
     for(int i=0, j=a.length-1; i<a.length && j>=0; i++, j--)
         ret[i] = a[j];
     return ret;
}

0
 public static int[] reverse(int[] array) {

    int j = array.length-1;
    // swap the values at the left and right indices //////
        for(int i=0; i<=j; i++)
        {
             int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
           j--;
        }

         return array;
    }

      public static void main(String []args){
        int[] data = {1,2,3,4,5,6,7,8,9};
        reverse(data);

    }

0
    public static void main(String args[])    {
        int [] arr = {10, 20, 30, 40, 50}; 
        reverse(arr, arr.length);
    }

    private static void reverse(int[] arr,    int length)    {

        for(int i=length;i>0;i--)    { 
            System.out.println(arr[i-1]); 
        }
    }

0

上面有一些很好的答案,但这是我的方法:

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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.