如何反转数组的切片 java

How to reverse slice of array java

我一直在尝试反转 java 中列表的一部分。

python 中的等价物(虽然可能不是最好的方法——我不关心这个,只是想表达我的观点)是:

myList = [0,1,2,3,4,5,6,7,8,9,10]
reverseSlice = myList[2:6]
reverseSlice.reverse()
myList[2:6] = reverseSlice

当我尝试在 Java 中手动实现时,我试过这个:

 public static int[] reverse(int[] x,int a1, int a2) {
    
    a1--;
    
    int[] rArr = new int[a2-a1+1];
    
    for (int ind = a1; ind<a2; ind++) {
        rArr[a2-ind-1] = x[ind];
    }
    
    for (int ind = a1; ind<a2; ind++) {
        x[ind] = rArr[ind];
    }
    
    return x;
    
}

然而,当我运行这个:

int[] cows1 = new int[]{0,1,2,3,4,5,6,7,8,9,10};
        
cows1 = reverse(cows1,2,6);
        
for (int i : cows1) {
    System.out.print(i + " ");
}

我得到 0 4 3 2 1 0 6 7 8 9 10 .

我真的很困惑我是怎么得到这个的,因为在我的函数中,我没有引入新值,所以“0”不应该出现。

我的问题:为什么我的代码返回的值不在列表中?

即将到来的 0 值可能是因为从 rArr 数组访问了一个未初始化的值。为了反转的目的,不需要额外的数组。您可以简单地将值从起始索引交换到结束索引。我测试了下面的代码,它给出了正确的输出

 public class Solution2 {
    
    public static void main(String args[])
    {
        int[] cows1 = new int[]{0,1,2,3,4,5,6,7,8,9,10};
        
        cows1 = reverse(cows1,2,6); 
        // both indices are inclusive 
                
        for (int i : cows1) {
            System.out.print(i + " ");
        }
    }
     public static int[] reverse(int[] x,int a1, int a2) {
            
            
            for (int i = 0; i < (a2-a1+1)/2; i++) {
               swap(x,a1+i,a2-i);
            }
            
            return x;
            
        }
    private static void swap(int[] x, int i, int j) {
//      System.out.println("values swappeed are "+ x[i] +  "  "  + x[j]);
        int temp = x[i];
        x[i] = x[j];
        x[j] = temp; 
        
        
    }
}

输出结果为

0 1 6 5 4 3 2 7 8 9 10  

问题似乎出在您的 reverse 函数的第一行:a1--; 没有保留起始索引的原始值。

方法调用

reverse 函数的目的是仅反转数组中受变量值 a1a2 约束的部分。附带一提,永远不要使用那样无意义的名称。这些变量的更好名称可能是 startIndexendIndex 或类似的命名(a1a2 没有任何意义)。

对于值 (2, 6),reverse 函数应该提取数组中从索引 2 开始到索引 6 结束的部分。我假设结束索引不包含在内,所以它应该仅获取索引 2、3、4 和 5 处的值。但是,该方法所做的第一件事是递减起始索引,因此它实际上从索引 1 开始。

从那里开始,该函数成功地反转了位于这些索引 [4,3,2,1] 的值。现在的问题是,索引 5 处的值会发生什么变化?让我们看看这部分代码做了什么new int[a2-a1+1]a2 的值为 6 而 a1new 的值为 1,因为它在第一行被递减了。这意味着您的新数组的大小为 [6-1+1],即 6。这似乎是不正确的。只需要反转 4 个值,数组的一个元素太大了。该数组的最后一个索引默认为 0.

的整数值

交换

第一个循环:

for (int ind = a1; ind<a2; ind++) { // starts with a1 = 1 and a2 = 6
    rArr[a2-ind-1] = x[ind]; // rArr[4] = x[1]: first iteration is off by 1
}

第二个循环:

for (int ind = a1; ind<a2; ind++) { // a1 = 1, a2 = 6 (starts at 1 and ends at 5  (rArr doesn't have an index 5)
    x[ind] = rArr[ind]; // first iteration: x[1] = rArr[1], last iteration x[5] = rArr[5] -> this last index is accessible because array was too big and was initialized to a primitive `int` default value (0).
}

解决方案

  • 确保保留开始和结束索引。
  • 使用原始开始和结束索引为您的计算分配临时数组(如果需要)。

reverse() 方法中,您的第一行应该是:

int[] rArr = new int[a2-a1]; // allocates an array of size 4 (6-2)

从这里开始,如果方法的其余部分是错误的,您将不会在反转数组中的任何位置看到零。在最坏的情况下,如果您的起始索引计算错误,您会遇到偏移问题。而且,我认为,这很容易被发现和修复。

如果您是编程新手,即使您更像是一名“专家”,您也应该始终在纸上(或板上)解决这些问题,然后再尝试编写代码并遍历您的逻辑。您会惊讶于在编写代码之前会发现多少逻辑错误。