给定一个整数数组 nums,将数组中的元素向右轮转 k个位置,其中 k是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
提示:
1 <= nums.length <=-231 <= nums[i] <=0 <= k <=
解题思路
- 处理有效轮转步数 :由于
k可能大于数组长度,先对k取模(k = k % len(nums)),确保k是有效步数。 - 三次翻转数组 :
- 翻转整个数组;
- 翻转前 k 个元素;
- 翻转剩余元素。
Python代码:
python
from typing import List
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
轮转数组:三次翻转法,原地修改,时间O(n),空间O(1)
"""
n = len(nums)
if n == 0: # 处理空数组边界情况
return
k %= n # 处理k超过数组长度的情况,取有效轮转步数
# 定义内部翻转函数(双指针法,原地修改数组)
def reverse(lst: List[int], start: int, end: int) -> None:
while start < end:
# 交换首尾元素,向中间逼近
lst[start], lst[end] = lst[end], lst[start]
start += 1
end -= 1
# 核心:三次翻转实现轮转
reverse(nums, 0, n - 1) # 第一步:翻转整个数组
reverse(nums, 0, k - 1) # 第二步:翻转前k个元素
reverse(nums, k, n - 1) # 第三步:翻转剩余元素
# 测试用例验证
if __name__ == "__main__":
# 示例1:基础用例
nums1 = [1, 2, 3, 4, 5, 6, 7]
k1 = 3
solution = Solution()
print(f"原始数组1: {nums1}, 轮转步数k={k1}")
solution.rotate(nums1, k1)
print(f"轮转后数组1: {nums1}") # 预期输出:[5,6,7,1,2,3,4]
# 示例2:k大于数组长度的情况
nums2 = [-1, -100, 3, 99]
k2 = 2
print(f"\n原始数组2: {nums2}, 轮转步数k={k2}")
solution.rotate(nums2, k2)
print(f"轮转后数组2: {nums2}") # 预期输出:[3,99,-1,-100]
# 边界用例1:空数组
nums3 = []
k3 = 5
print(f"\n原始数组3: {nums3}, 轮转步数k={k3}")
solution.rotate(nums3, k3)
print(f"轮转后数组3: {nums3}") # 预期输出:[]
# 边界用例2:k=0(无需轮转)
nums4 = [1, 2, 3]
k4 = 0
print(f"\n原始数组4: {nums4}, 轮转步数k={k4}")
solution.rotate(nums4, k4)
print(f"轮转后数组4: {nums4}") # 预期输出:[1,2,3]
# 边界用例3:数组长度为1
nums5 = [10]
k5 = 100
print(f"\n原始数组5: {nums5}, 轮转步数k={k5}")
solution.rotate(nums5, k5)
print(f"轮转后数组5: {nums5}") # 预期输出:[10]
LeetCode提交代码:
python
class Solution:
from typing import List
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
k %= n # 处理k超过数组长度的情况
# 定义翻转函数(双指针法,原地修改)
def reverse(lst, start, end):
while start < end:
lst[start], lst[end] = lst[end], lst[start]
start += 1
end -= 1
# 三次翻转
reverse(nums, 0, n - 1) # 翻转整个数组
reverse(nums, 0, k - 1) # 翻转前k个元素
reverse(nums, k, n - 1) # 翻转剩余元素
程序运行结果如下:
bash
原始数组1: [1, 2, 3, 4, 5, 6, 7], 轮转步数k=3
轮转后数组1: [5, 6, 7, 1, 2, 3, 4]
原始数组2: [-1, -100, 3, 99], 轮转步数k=2
轮转后数组2: [3, 99, -1, -100]
原始数组3: [], 轮转步数k=5
轮转后数组3: []
原始数组4: [1, 2, 3], 轮转步数k=0
轮转后数组4: [1, 2, 3]
原始数组5: [10], 轮转步数k=100
轮转后数组5: [10]
总结
本文介绍了一种原地轮转数组的高效算法。通过三次翻转操作实现数组右移k位:首先计算有效轮转步数k=k%n,然后依次翻转整个数组、前k个元素和剩余元素。该方法时间复杂度O(n),空间复杂度O(1),适用于各种边界情况(空数组、k=0、k>n等)。Python实现采用双指针翻转函数,代码简洁高效,已通过LeetCode测试用例验证。