【问题标题】:How do I reverse an int array in Java?如何在 Java 中反转 int 数组?
【发布时间】:2010-01-26 06:09:17
【问题描述】:

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

这有什么问题?

【问题讨论】:

标签: java arrays idioms


【解决方案1】:

要反转一个 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循环的外面。
  • @Jin 我不会。它只会混淆含义,我敢打赌优化编译器无论如何都会为你做这件事。无论如何,除非您从分析中获得明确的证据表明它是必要的/有帮助的,否则微优化是没有意义的。
  • @JinKwon 这有点像validData.length &gt;&gt; 1。这是等效的,而且速度更快,但它使许多程序员感到困惑,任何好的编译器都会自动做到这一点。
  • 您应该只计算一次validData.length - i - 1 并将其保存到变量中。
  • 任何人都可以建议在没有临时变量的情况下进行逆转!!
【解决方案2】:

有了Commons.Lang,你可以简单地使用

ArrayUtils.reverse(int[] array)

大多数情况下,在解决您的问题时,坚持使用已经过单元测试和用户测试的易于使用的库会更快、更安全。

【讨论】:

  • 我希望它返回反向(通过)数组以获得类似功能的样式。
  • @laurent-g 公平地说:以这种方式反转数组更节省内存,这可能就是他们这样做的原因。
  • 我的意思不是复制还是不复制。我的消息指出要返回“(通过)”(在被反转之后),因此它可以在表达式中传递,而不需要单独的语句。
  • 如果我不想使用 ArrayUtils 怎么办?你怎么能手动呢?
  • @LaurentG 做一个辅助函数private int[] reversed(int[] array) {ArrayUtils.reverse(array);} 然后你可以做f(reversed(arr)); :))
【解决方案3】:
Collections.reverse(Arrays.asList(yourArray));

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

成本只是创建一个列表对象,不需要额外的库。

Tarik 及其评论者的回答中已经提出了类似的解决方案,但我认为这个答案会更简洁,更容易解析。

【讨论】:

  • 对于对象数组,这是一个很好的解决方案。但它不适用于基元数组。例如。将int[] 传递给asList(...) 不会返回List&lt;Integer&gt;,而是返回List&lt;int[]&gt;,包含一个元素。 AFAICS 没有简单的内置方法可以将 int[] 转换为 Integer[]
  • 这不适用于原始数组......集合不会返回一个值,所以现在你有一个无用的数组作为内存中的列表
  • @MartinRust Java 8+:Arrays.stream(arr).boxed().collect(Collectors.toList())Arrays.stream(arr).boxed().toArray(Integer[]::new)
  • @KingLogic 好吧,这是一个单行字,也是我能想到的最漂亮的东西。随意提出更好的建议(不依赖于库)。
【解决方案4】:
public class ArrayHandle {
    public static Object[] reverse(Object[] arr) {
        List<Object> list = Arrays.asList(arr);
        Collections.reverse(list);
        return list.toArray();
    }
}

【讨论】:

  • 当然会。一个列表只能保存对象,而不是原语,因此所有原语(在这种情况下为ints)都被包装到它们各自的包装器(在这种情况下为Integers)并放入列表中。你看,Integers 是对象。 @汤姆
  • 注意:如果我没记错的话,原始数组会被修改。为了清楚起见,您可能只想不返回任何东西。
  • @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 - 就地算法使用更少的内存并且运行得更快。
  • @Andrea 实际上不是。 Arrays.asList() 返回的列表没有引用原始数组,返回的数组也没有。这是这种方法的问题之一:它使用了三倍的内存,并且作为就地算法完成了三倍的工作。
  • 此方法本身可能有效,但不能将int[] 作为参数传递给此方法(“不兼容的类型:int[] 无法转换为 Object[]” i>)。
【解决方案5】:

我认为,如果您声明显式变量以跟踪您在循环的每次迭代中交换的索引,那么遵循算法的逻辑会更容易一些。

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

【讨论】:

  • 老派交换看起来更容易,但是当涉及数组索引值时,左,右,...如果有的话,将有助于调试
  • 您还可以添加 'public static void swap(int[] data, int index1, int index2) { ... }' 并像这样从 'reverse' 使用它:swap(data, left ,对)。
【解决方案6】:

这里已经有很多答案了,主要集中在就地修改数组。但为了完整起见,这里有另一种方法,使用 Java 流来保留原始数组并创建一个新的反转数组:

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

【讨论】:

    【解决方案7】:

    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]
    

    【讨论】:

      【解决方案8】:

      使用番石榴:

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

      【讨论】:

      • 这太棒了!简短而有效。像所有asList 方法一样,它创建一个直接写入支持(原始)数组的view。我认为这里的投票者错误地认为这返回了一个盒装列表或其他东西。
      • @LukeUsherwood 大概在每个元素上调用 get 和 set 时仍然会有一些来自装箱和拆箱的开销。但我同意你的观点,这是一个绝妙的解决方案。
      • 确实,这值得留意。我认为在我个人使用的大多数代码中这没什么大不了的——我们的“热门”区域定义明确,其余部分是“胶水代码”。同时,我意识到内存流失还会产生额外的“隐藏”成本,分析器不会将其归因于实际功能。
      • @LukeUsherwood 它仍然返回一个装箱列表而不是一个原始数组
      • @AnthonyJClink 不确定“它”指的是什么,但 JDK 实用程序 Collections.reverse 是一个 void 方法。这在包装 int[] 的 Guava 内部类上就地运行(因为它从不存储盒装 Integers 的列表,我不会将该类称为“盒装列表”,而是称为“列表视图”大批”)。但是是的,它通过一个传递Integer 对象的接口进行操作,所以这会产生大量的临时对象流失和装箱,如前所述。尝试使用IntStream 或原始集合库来解决性能问题。 (Trove、Koloboke、Eclipse Collections、...)
      【解决方案9】:
      for(int i=validData.length-1; i>=0; i--){
        System.out.println(validData[i]);
       }
      

      【讨论】:

      • 不幸的是,这是这里最干净的答案,因为每个开发人员都知道如何去做,而且不需要安装任何扩展包。
      • 这对于获取数组的值很有用,但是如果您真的想反转数组,则必须使用此方法创建一个新的 => 其他的会更有效。
      【解决方案10】:

      简单的for循环!

      for (int start = 0, end = array.length - 1; start <= end; start++, end--) {
          int aux = array[start];
          array[start]=array[end];
          array[end]=aux;
      }
      

      【讨论】:

      • 以后请让提问者具体知道他们做错了什么,你做对了什么。
      • start &lt;= end更改为start &lt; end
      【解决方案11】:

      这对你有帮助

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

      【讨论】:

        【解决方案12】:

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

        希望你能从中有所收获。

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

        【讨论】:

        • 使用原语不能解决原来的问题。
        • 有很多方法可以将 prims 转换为对象。我总是建议在 java 中尽可能避免使用 prims,我也认为应该鼓励它。
        • 将未知长度的基元数组转换为数组可能是一个非常糟糕的主意,尤其是在没有意识到的情况下。 Java 不是 Smalltalk。原语是语言的一部分并且有自己的位置。我们不喜欢它们也没关系,我们必须接受它们,并在适当的地方使用它们。
        • 你实际上不需要复制数组,只需Collections.reverse(asList(arraytoReverse)); return arrayToReverse;asList 只是对数组的一个包装,所以把原来的数组颠倒过来了。
        【解决方案13】:

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

        【讨论】:

          【解决方案14】:

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

          【讨论】:

          • 也许您的意思是将交换作为内联交换的伪代码而不是方法调用,但如果不是,那将不起作用。 Java 通过引用传递,因此无法为变量编写交换方法。
          • 我的意思是你可以让 v[i] 和 v[j] 交换。我知道方法调用在 java 中是如何工作的。对于方法,您可以执行类似 swap(v, i++, j--);
          • Dean,数组validData是一个对象,通过引用传递,所以swap()方法可以完美运行。
          【解决方案15】:

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

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

          【讨论】:

            【解决方案16】:

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

            我不确定 Aaron 的解决方案是否可以通过此调用 Collections.reverse(list); 进行此操作@ 有人知道吗?

            【讨论】:

            • 在数组上向后迭代需要一个新数组。我喜欢上面发布的解决方案,它在不创建新数组的情况下进行内联反转。
            • @Simucal 为什么要创建一个新数组?只需向后迭代即可。
            【解决方案17】:
            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;
                    }
                }
            

            【讨论】:

              【解决方案18】:

              时间复杂度为 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 &lt; end; start++, end--) { ... }
              【解决方案19】:

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

              1.在空间中反转数组。

              步骤 1. 交换开始和结束索引处的元素。

              第二步,增加起始索引,减少结束索引。

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

              【讨论】:

                【解决方案20】:
                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]);
                  }
                }
                

                【讨论】:

                • 是的,我尝试过相同且清晰的代码,输出为 int[] a = {1,3,5,2,6,7}; for(int i = a.length-1;i>=0;i--) {System.out.print(a[i]+" ");}` 它将数组从最后一个索引反转到第一个索引
                【解决方案21】:

                这样做不会更不容易出错吗?

                    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;
                

                【讨论】:

                  【解决方案22】:

                  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]

                  【讨论】:

                  • 什么是Ints
                  • @CodingNow 它是 Guava 实用程序助手类之一 - 请参阅 here
                  【解决方案23】:
                      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]); 
                          }
                      }
                  

                  【讨论】:

                    【解决方案24】:

                    下面是在您的机器上运行的完整程序。

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

                    对于使用数组的矩阵程序this will be the good source。通过链接。

                    【讨论】:

                      【解决方案25】:

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

                      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/

                      【讨论】:

                        【解决方案26】:
                        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;
                        } 
                        

                        【讨论】:

                        • 请考虑在您的答案中添加解释。仅代码答案无法解释任何内容。
                        【解决方案27】:

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

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

                        【讨论】:

                          【解决方案28】:

                          这是我想出的:

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

                          【讨论】:

                            【解决方案29】:
                            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;
                            }
                            

                            【讨论】:

                              【解决方案30】:
                               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);
                              
                                  }
                              

                              【讨论】:

                                猜你喜欢
                                • 2021-12-11
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2017-11-20
                                • 1970-01-01
                                • 1970-01-01
                                • 2015-10-02
                                • 2022-06-12
                                相关资源
                                最近更新 更多