「这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战」
描述
Given an array, rotate the array to the right by k steps, where k is non-negative. Follow up:
- Try to come up with as many solutions as you can. There are at least three different ways to solve this problem.
- Could you do it in-place with O(1) extra space?
Example 1:
Input: nums = [1,2,3,4,5,6,7], k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
Example 2:
Input: nums = [-1,-100,3,99], k = 2
Output: [3,99,-1,-100]
Explanation:
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]
Note:
1 <= nums.length <= 10^5
-2^31 <= nums[i] <= 2^31 - 1
0 <= k <= 10^5
解析
根据题意,给定一个数组,将数组向右旋转 k 步,其中 k 为非负数。题目提出来更高的要求:
- 尝试想出尽可能多的解决方案。 至少三种不同的方法可以解决这个问题
- 用 O(1) 额外的空间就地完成
要想使用 O(1) 的额外空间,那就说说明只能在 nums 本身进行改动,我们最先想到的思路,就是很朴素的一种。按照题目的描述,我们是将 nums 看成一个圆,向右转了 k 个元素形成的结果,所以由上可知:
- 直接进行 k 次的遍历
- 每次遍历将 nums 的所有元素都向右移动一位
- 执行完上述的操作得到的 nums 即为结果。
时间复杂度为 O(k*N) ,空间复杂度为 O(1) 。
解答
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
N = len(nums)
k = k % N
if k == 0 : return nums
for _ in range(k):
t = nums[-1]
for i in range(N-1,0,-1):
nums[i] = nums[i-1]
nums[0] = t
运行结果
Time Limit Exceeded
解析
其实就是将后面的 k 个元素进行逆向反转得到 t ,然后将 nums[:N-k] 赋值给 nums[k:] ,然后将 t 赋值给 nums[:k] 也是符合题意的操作,这种解法的空间复杂度为 O(1) ,时间复杂度为 O(N) 。
解答
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
N = len(nums)
k = k % N
if k == 0 : return nums
t = nums[-k:]
nums[k:] = nums[:N-k]
nums[:k] = t
运行结果
Runtime: 341 ms, faster than 11.28% of Python online submissions for Rotate Array.
Memory Usage: 25.1 MB, less than 39.85% of Python online submissions for Rotate Array.
解析
其实这道题还可以使用一种反转的规律还进行解题,如下所示:
- 最初的数组 nums 表示如下 : 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
所以我们定义一个 reverse 函数将上面的三个过程进行执行即可,需要注意的是 k 在这里要对 nums 的长度取模,因为 k 如果太大的时候只需要知道 k%len(nums) 是多少即可,中间很多次整数组的移动对于结果没有影响,不但增加计算量,还会使函数不能正确运行。
时间复杂度为 O(N) ,空间复杂度为 O(1) 。
解答
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: None Do not return anything, modify nums in-place instead.
"""
k %= len(nums)
self.reverse(nums, 0, len(nums)-1)
self.reverse(nums, 0, k-1)
self.reverse(nums, k, len(nums)-1)
def reverse(self, nums, start, end):
while start<end:
tmp = nums[start]
nums[start] = nums[end]
nums[end] = tmp
start += 1
end -= 1
运行结果
Runtime: 267 ms, faster than 34.40% of Python online submissions for Rotate Array.
Memory Usage: 25.1 MB, less than 15.20% of Python online submissions for Rotate Array.
原题链接
您的支持是我最大的动力