旋转整数数组的递归方法分析

Analysis of recursive approach for rotating an array of integers

在LeetCode上解决Array rotation的时候,写了一个递归算法来解决这个问题:

Given an array, rotate the array to the right by k steps, where k is non-negative.

Example 1:

Input: nums = [1,2,3,4,5,6,7], k = 3 Output: [5,6,7,1,2,3,4] Explanation: rotate 1 steps to the right: [7,1,2,3,4,5,6] rotate 2 steps to the right: [6,7,1,2,3,4,5] rotate 3 steps to the right: [5,6,7,1,2,3,4]

Example 2:

Input: nums = [-1,-100,3,99], k = 2 Output: [3,99,-1,-100] Explanation: rotate 1 steps to the right: [99,-1,-100,3] rotate 2 steps to the right: [3,99,-1,-100]

Constraints:

1 <= nums.length <= 2*104
-231 <= nums[i] <= 231 - 1
0 <= k <= 105

为了进一步说明问题 link 是 here.

我想出的解决方案如下:

class Solution {
  public void rotate(int[] nums, int k) {
    rotateArr(nums, nums.length, k % nums.length, 0);
  }

  public static void rotateArr(int[] arr, int len, int steps, int current) {
    if (len <= steps) {
      return;
    }
    rotateArr(arr, len - 1, steps, current + 1);
    int stepsTaken = 0;
    int i = current;
    int temp;
    while (stepsTaken < steps) {
      temp = arr[i];
      arr[i] = arr[i + 1];
      arr[i + 1] = temp;
      i++;
      stepsTaken++;
    }
  }
}

根据我对解决方案的分析,函数 rotateArr() 将首先通过递归 nums.length - k 次。之后它开始征服,这将在 nums.length - k + 1 步中发生,并且在每一步中执行 k 操作。总结我们得到的一切:

虽然我有一个二次项但它是一个常数,因此我相信我的运行时间是 O(n)。
我想知道以下内容:

Utkarsh Tiwari,我认为您的分析不正确。根据我的计算,征服步骤将发生 A.length - k 次并且 不会 A.length - k + 1.

让我们考虑您提到的第二个输入数组:

[-1, -100, 3, 99]

这里第一次调用rotateArray(A, 4, 2, 0)发生在main()方法中。第二个递归调用是这样的:rotateArray(A, 3, 2, 1) 最后一个是这样的:rotateArray(A, 2, 2, 2).

但是,在最后一次递归调用中,由于满足基本条件,因此不会发生征服。

if(length <= steps) return.

该函数将简单地 return 最后一次,而不执行任何重要步骤。 因此,所有 k 次操作将仅发生在前两个递归调用中,在这种情况下根据表达式 A.length - k4-2

因此,time complexity 将是 (A.length-k) * k

现在,让我们看看您提供的约束条件:

1 <= nums.length <= 2 * 10^4

-2^31 <= nums[i] <= 2^31 - 1

0 <= k <= 10^5

在这里,k 而不是 常数。它的可能值甚至超过了nums.length的最大值。 time complexity 取决于 both 取决于 A.lengthk 的值。 如果 k 的可能值介于 5 到 20 之间,则应该是 O(nums.length)。但是,在当前限制条件下,它可以取一个大于 A.length 的值。

让我们注意您的实施中的另一个细微细节。在对 rotateArray() 的第一次调用中,您将 k % A.length 作为参数之一传递。现在 k 的可能值减少为:

0 <= k < A.length

如果我们选择 k 的值为 A.length/2 并输入我们的时间复杂度,我们得到:

(A.length - A.length/2) * A.length

减少到 O(A.length^2),这将是 worst case complexity

希望对您有所帮助。 如果您在解决方案中遇到任何问题,请发表评论。