15. 轮转数组
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例:
输入: 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]
常用的算法分别是:切片拼接法、类法 deque、函数法 roll 和 原地交换法。
使用切片拼接轮转数组的思路:
# 切片拼接法 时间复杂度:O(n) 空间复杂度:O(n)
def rotate1(nums, k):
n = len(nums)
k = k % n
nums[:] = nums[-k:] + nums[:-k]
return nums
# 切片拼接法2 时间复杂度:O(n) 空间复杂度:O(n)
def rotate1_1(nums, k):
# 海象表达式:指定表达式 := 可以在赋值的同时判断值是否为真
if k := (k % len(nums)):
nums[:k], nums[k:] = nums[-k:], nums[:-k]
时间复杂度:O(N),需要遍历数组一次进行切片拼接操作。
空间复杂度:O(N),切片操作会生成新的数组,需要额外线性空间。
# 类法deque() 时间复杂度:O(n) 空间复杂度:O(n)
def rotate2(nums, k):
n = len(nums)
k = k % n
q = deque(nums)
q.rotate(k)
return list(q)
时间复杂度:O(N),转换为deque和list各需一次线性遍历。
空间复杂度:O(N),创建deque需占用线性额外空间。
# 函数法roll() 时间复杂度:O(n) 空间复杂度:O(n)
def rotate3(nums, k):
n = len(nums)
k = k % n
arr = np.array(nums)
arr = np.roll(arr, k)
return list(arr)
时间复杂度:O(N),转换为数组和列表各需线性时间。
空间复杂度:O(N),生成numpy数组需线性大小空间。
使用原地交换法轮转数组的思路:
# 原地交换法 时间复杂度:O(n) 空间复杂度:O(1)
def rotate4(nums, k):
n = len(nums)
k = k % n # 计算实际需要移动的位置
start = count = 0
while count < n: # 外层循环n次
current = start
prev = nums[start] # 保存当前元素
while True:
next_idx = (current + k) % n # 计算目标位置
nums[next_idx], prev = prev, nums[next_idx] # 交换元素
current = next_idx
count += 1
if start == current: # 一轮轮转结束
break
start += 1
return nums
时间复杂度:O(N),外层循环N次,内层循环次数不确定但也是N级别,总体是线性级别。
空间复杂度:O(1),直接在原数组上修改,只用了两个变量,所以空间复杂度是常数级别。
题目来源:力扣