ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Java 中反转 int 数组?

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

它有什么问题?

我明白我做错了什么。应该是validData.length/2。否则它将自行反转,然后自行反转。
请参阅 en.wikipedia.org/wiki/In-place_algorithm,其中包含对该算法正确版本的描述。

3
3lectrologos

要反转 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 >> 1。这是等效的并且更快,但它使许多程序员感到困惑,任何好的编译器都会自动做到这一点。
您应该只执行一次此计算 validData.length - i - 1 并将其保存到变量中。
任何人都可以建议没有临时变量的逆转!
M
Manur

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

ArrayUtils.reverse(int[] array)

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


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

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

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

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


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

当然会的。一个列表只能包含对象,而不是基元,因此所有基元(在本例中为 int)都被包装到它们各自的包装器(在本例中为 Integer)并放入列表中。你看,Integer 是对象。 @汤姆
注意:如果我没记错的话,原始数组会被修改。为了清楚起见,您可能只想不返回任何东西。
@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[]”)。
B
Bill the Lizard

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

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, right)。
P
Patrick Parker

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

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

L
Laser Infinite

对于 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]

Z
ZhekaKozlov

与番石榴:

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

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

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

简单的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 <= end 更改为 start < end
R
Radiodef

这将帮助你

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

A
AnthonyJClink

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

我希望你能从中有所收获。

@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 只是数组的一个包装器,因此原始数组是相反的。
A
AbsoluteBlue

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

f
fastcodejava

您的程序仅适用于 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() 方法可以完美运行。
K
Karan Khanna

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

1. 在空间中反转一个数组。

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

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

Step 3. 迭代 Step 1 和 Step 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);
}

ס
סטנלי גרונן

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

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

N
Nick Strupat

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

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


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

u
user11016

具有 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--) { ... }
U
Udo Held
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]+" ");}` 它将数组从最后一个索引反转到第一个索引
M
Moddl

这样做不会更不可能出错吗?

    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;

v
vikarjramun

使用 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/


S
Sameer Shrestha

2 种反转 Array 的方法。

使用 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;数组[i] = 数组[索引];数组[索引] = 温度; } System.out.println(Arrays.toString(array)); } 使用内置函数 (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
K
Kalidindi Prashanth
    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]); 
        }
    }

M
Mdhar9e

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

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 的矩阵程序。通过链接。


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

请考虑为您的答案添加解释。仅代码的答案不能解释任何事情。
c
craftsmannadeem

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

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

S
Simple-Solution

这是我想出的:

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

Z
Z A Abbasi
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;
}

r
roshan posakya
 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);

    }