【问题标题】:How to reverse slice of array java如何反转数组java的切片
【发布时间】:2022-01-13 02:12:09
【问题描述】:

我一直在尝试在 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”不应该出现。

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

【问题讨论】:

  • 两个索引都包含在反转中吗?
  • 我试过调试,但还没有真正看到这是怎么回事。
  • @GurkiratSinghGuliani 它应该反转从索引 a1-1 到 a2-1 的所有内容,包括
  • @Ryan Fu 输入数组 ( 0,1,2,3,4,5) 和 reverse(arr,2,4) 输出将是 ( 0,1,4,3,2, 5) ?
  • 不要将基于 1 的索引和基于 0 的索引混合在一起。这只会让事情变得混乱。将所有内容都写在从 0 开始的索引中,然后如果您真的需要从 1 开始的索引功能,只需编写一个辅助函数。

标签: java arrays reverse


【解决方案1】:

即将出现的 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  

【讨论】:

  • 注意此解决方案中如何保留 a1a2 原始值。这个(a2-a1+1)/2 和这个swap(x,a1+i,a2-i) 都没有改变这两个索引的原始值。如果您需要根据这些索引重新计算偏移量,则计算将始终正确。如果您需要基于新偏移量的计算,请将它们保存在不同的变量中。
【解决方案2】:

问题似乎是您的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)

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 2019-06-15
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多