返回

巧用指针,实现数组旋转:LeetCode 189. 旋转数组

闲谈

如何轻松旋转数组:LeetCode 189 详解

背景

准备好了吗?让我们潜入计算机编程世界的迷人世界,解决一个备受程序员青睐的难题:LeetCode 189 旋转数组。

挑战:旋转数组

想象一下你面前有一个装满数字的数组,就像魔方上的九个方块。你的任务是将这个数组向右旋转 k 步,就好像你在玩一个数字魔方一样。

举个例子,如果你有一个数组 [1, 2, 3, 4, 5, 6, 7],并且需要向右旋转 3 步,那么结果应该是 [5, 6, 7, 1, 2, 3, 4]。

乍一看,这似乎是一个简单的任务,但魔鬼藏在细节里。我们不能使用额外的存储空间,而且必须考虑数组的循环性质。

分而治之的策略

让我们将这个难题分解成更易于管理的部分。我们可以将数组分成两个部分:旋转部分和非旋转部分。

旋转部分包含数组的最后 k 个元素,而非旋转部分则包含其余元素。

旋转步骤

现在,让我们开始旋转!

  1. 旋转部分: 我们从旋转部分的末尾开始,将每个元素向后移动一步,直到到达非旋转部分的末尾。

  2. 非旋转部分: 接下来,我们将非旋转部分的每个元素向前移动一步,直到到达旋转部分的开头。

  3. 合并数组: 最后,我们将旋转部分和非旋转部分合并在一起,形成最终的旋转数组。

代码实现

def rotate(nums, k):
  """
  Rotates the array nums to the right by k steps.

  Args:
    nums: The array to be rotated.
    k: The number of steps to rotate the array to the right.

  Returns:
    None. The array nums is rotated in-place.
  """

  # Determine the rotation's starting and ending positions.
  start = len(nums) - k
  end = len(nums)

  # Divide the array into two parts: the rotation part and the non-rotation part.
  rotation_part = nums[start:]
  non_rotation_part = nums[:start]

  # Rotate the rotation part.
  for i in range(len(rotation_part) - 1, 0, -1):
    nums[i] = nums[i - 1]

  # Rotate the non-rotation part.
  for i in range(len(non_rotation_part) - 1, 0, -1):
    nums[i] = nums[i - 1]

  # Merge the rotation part and the non-rotation part.
  nums[:k] = rotation_part
  nums[k:] = non_rotation_part

复杂度分析

  • 时间复杂度:O(n),其中 n 为数组的长度。我们只需要遍历数组一次,因此时间复杂度是线性的。

  • 空间复杂度:O(1)。我们没有使用额外的存储空间,因此空间复杂度是常数。

常见问题解答

  1. 为什么我们需要分成旋转部分和非旋转部分?

    这样做可以让我们专注于需要旋转的部分,而无需移动数组中的每个元素。

  2. 旋转时为什么要向后移动元素而不是向前移动?

    向后移动元素可以避免覆盖已经移动的元素。

  3. 如果 k 比数组的长度还大怎么办?

    在这种情况下,我们可以对 k 取模,以确定实际的旋转步数。

  4. 这个算法可以适用于任何数据类型吗?

    是的,这个算法可以适用于任何数据类型,只要它们支持下标访问。

  5. 还有什么方法可以解决这个问题吗?

    有其他方法,例如使用额外的存储空间或循环遍历 k 次数组。但是,分而治之的方法在效率和简洁性方面具有优势。

结论

恭喜你征服了 LeetCode 189!你掌握了旋转数组的技巧,为解决更复杂的编程难题奠定了坚实的基础。

记住,编程是一场持续的学习之旅。每当遇到新的挑战时,请尝试分解问题,寻找模式,并用创造性和高效的方法来解决它们。