【问题标题】:rotate the elements of the given array k times to the right将给定数组的元素向右旋转 k 次
【发布时间】:2021-09-18 21:31:46
【问题描述】:

我已编写此代码以将数组旋转 k 次。在此,当我添加 i=0 时,它显示“ArrayOutOfBounds”异常,当我将 i 的值更改为 1 时,它显示错误输出。为什么显示此异常?有什么办法可以纠正这个代码吗?

    public void rotate(int[] nums, int k)
    { int j=0, temp=0;
        for(j=0;j<k;j++)
        {
        for(int i=0;i<nums.length;i++)
        {
              temp=nums[i-1];
              nums[i-1]=nums[i];
              nums[i]=temp;
            
        }
            
        }
    }
}

【问题讨论】:

  • 对于i=0nums[i-1] 变为nums[-1]
  • 如果 i 为 0,您将尝试获取 -1 的索引,这将引发 ArrayOutOfBounds 异常。如果 i 从 1 开始,那么你不是在处理第一个数字。
  • @DavidLee,我有什么可以改变的来避免这个错误并在这个程序中得到正确的输出吗?
  • 为什么每次swap都需要迭代k次?你可以直接做k-shift,算法变成O(n)而不是O(n*k)。

标签: java arrays for-loop exception


【解决方案1】:

编辑(来自上面的 cmets):如果 i 为 0,则您试图获取 -1 的索引,这将引发 ArrayOutOfBounds 异常。如果 i 从 1 开始,那么您不是在处理第一个数字。

这是您可以用来将整数向右旋转的函数:

public void rotate(int[] nums, int k) {
    int arrLen = nums.length;

    // If the number of times you want to rotate is bigger than the size of the array, get the minimum number of rotations to get the same result.
    while (k > n) {
        k = k - arrLen;
    }
    k = arrLen - k;
    k = k % arrLen;
    int i, m, n, temp;
    int g_c_d = gcd(k, arrLen);
    // Move the value in the i-th index
    for (i = 0; i < g_c_d; i++) {
        temp = arr[i];
        m = i;
        while (true) {
            n = m + k;
            if (n >= arrLen) {
                n = n - arrLen;
            }
            if (n == i) {
                break;
            }
            arr[m] = arr[n];
            m = n;
        }
        arr[m] = temp;
    }
}

// Find the greatest common divisor of two numbers, a and b
public void gcd(int a, int b) {
    if (b == 0) {
        return a;
    } else {
        return gcd(b, a % b);
    }
}

让我简要解释一下它的作用。这是最知名的算法之一:杂耍。您将数组划分为 n 个集合,其中 n 表示数组长度和要旋转的次数的最大公约数。然后,您在集合内移动数字。

就时间而言,这可能是最有效的(因为它的时间复杂度是 O(n))。

【讨论】:

  • 是的,另一个显示超过时间限制,这个效果更好。
【解决方案2】:

i=0,您尝试访问nums[i-1] = num[-1],这是一个无效位置,因此会引发ArrayOutOfBound 异常。
所以,修改后的版本是:

        for (j=0; j<k; j++)
        {
            for (int i=1;i<nums.length;i++)
            {
                temp=nums[i-1];
                nums[i-1]=nums[i];
                nums[i]=temp;
            } 
        }

但是当您将元素向左移动时,上述内容会将数组向left 旋转k 次而不是向右。因此,要获得 right 旋转,您需要从数组末尾移动元素。喜欢:

        for (j=0; j<k; j++)
        {
            for (int i=nums.length-1; 0<i; i--)
            {
                // shifting towards the right
                temp=nums[i-1];
                nums[i-1]=nums[i];
                nums[i]=temp;
            } 
        }

【讨论】:

    【解决方案3】:

    更好的解决方案是使用值“0”获取给定数组的副本,然后遍历给定数组以获得新索引。

    顺时针旋转数组的 New_index 公式:

    for(int i=0;i<nums.length;i++){
     int new_index = (old_index+k)%(a.length)
     copy[new_index] = a[old_index]
    }
    
    Now the entire function code would be:
    
        
    public static void rotate(int[] a, int k)
        {
         int n = a.length;
         int[] copy = new int[n];
        //  fill the values with zeroes
         for(int i=0;i<n;i++){
             copy[i]=0;
         }
        //  rotate the array
        for(int i=0;i<n;i++){
            int new_index = (i+k)%n;
            copy[new_index] = a[i];
        }
        // Now that the array is copied, copy the elements to the original array. Because they asked to rotate the given array.
        for(int i=0;i<n;i++){
             a[i]=copy[i];
         }
        }
    

    【讨论】:

      猜你喜欢
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多