问题描述
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
问题分析
- 数组轮转:将数组中的元素向右移动
k
个位置,超出数组长度的部分会循环到数组的开头。 - 边界条件:如果
k
大于数组的长度n
,则实际轮转次数为k % n
次(因为每n
次轮转后,数组会恢复原状)。 - 时间复杂度:我们希望算法尽可能高效,时间复杂度为 O(n)。
- 空间复杂度:我们希望尽可能少用额外空间,最好是 O(1)。
实现步骤
- 计算有效的轮转次数:
k = k % len(nums)
。 - 反转整个数组:将数组的所有元素反转。
- 反转前
k
个元素:将前k
个元素再反转回来。 - 反转剩余部分:将剩下的元素再反转回来。
代码实现
def rotate(nums, k):
"""
将数组 nums 向右轮转 k 个位置
:param nums: List[int] - 待轮转的数组
:param k: int - 轮转的步数
:return: None - 原地修改数组
"""
n = len(nums)
k = k % n # 处理 k 大于数组长度的情况
def reverse(start, end):
"""反转数组中指定区间的元素"""
while start < end:
nums[start], nums[end] = nums[end], nums[start]
start += 1
end -= 1
# 反转整个数组
reverse(0, n - 1)
# 反转前 k 个元素
reverse(0, k - 1)
# 反转剩余的元素
reverse(k, n - 1)
# 示例
nums = [1, 2, 3, 4, 5, 6, 7]
rotate(nums, 3)
print(nums) # 输出: [5, 6, 7, 1, 2, 3, 4]
详细解释
-
计算有效的轮转次数:
k = k % n
- 如果
k
大于数组长度n
,则实际轮转次数应为k % n
次。
- 如果
-
反转整个数组:
- 例如,数组
[1, 2, 3, 4, 5, 6, 7]
反转后变成[7, 6, 5, 4, 3, 2, 1]
。
- 例如,数组
-
反转前
k
个元素:- 例如,前
3
个元素[7, 6, 5]
反转后变成[5, 6, 7]
。
- 例如,前
-
反转剩余部分:
- 例如,剩余的元素
[4, 3, 2, 1]
反转后变成[1, 2, 3, 4]
。 - 最终数组变为
[5, 6, 7, 1, 2, 3, 4]
。
- 例如,剩余的元素
知识点总结
- 数组反转是一种常见的技巧,可以用来解决数组轮转问题。
- 通过三次反转操作,可以在 O(n) 的时间复杂度内完成数组的右轮转,且只使用 O(1) 的额外空间