题目描述
给定一个数组,将数组中的元素向右移动 k
个位置,其中 k
是非负数。
解题思路一:切片
第一步求出了k与nums长度的余数是为了避免出现k>len(nums)的情况出现, 然后在进行切片,把切下来的倒数k个元素放到列表最前面即可。值得注意的是,在python中以nums = nums[-k:]+…的形式不能顺利赋值,需要以全切的方式nums[:]才可以。
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
if k == 0: return
k = k%len(nums)
nums[:] = nums[-k:] + nums[:-k]
复杂度分析:
时间复杂度:O(N) 此算法时间都花在切片上,所以是O(N)
空间复杂度: O(N) 切片所开辟出来的空间为O(N)
解题思路二: 数组翻转
数组翻转也就是俗称的三次翻转
当我们将数组的元素向右移动k次后,尾部的n个元素会将移动到头部。那我们是否可以走这种思路:
- 先翻转整个数组,将尾部的元素翻转到头部
- 再翻转整个数组的前k个元素
- 最后再翻转数组后n-k个元素
以n=7,k=3为例
操作 | 结果 |
---|---|
原始数组 | 1 2 3 4 5 6 7 |
翻转整个数组 | 7 6 5 4 3 2 1 |
翻转前k个元素 | 5 6 7 4 3 2 1 |
翻转后n-k个元素 | 5 6 7 1 2 3 4 |
代码实现
class Solution:
def rotate(self, nums: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
def reverse(nums, start, end):
while start < end:
tmp = nums[start]
nums[start] = nums[end]
nums[end] = tmp
start += 1
end -= 1
k %= len(nums)
reverse(nums, 0, len(nums)-1)
reverse(nums, 0, k-1)
reverse(nums, k, len(nums)-1)
复杂度分析
时间复杂度 O(N) 进行了三次翻转,每个元素被翻转了两次,操作次数为2n = O(N)
空间复杂度 O(1) 空间上只用了tmp整个临时变量,复杂度为常数复杂度O(1)