LeetCode—189. Rotate Array 滚动数组
题目
给定数组和滚动步数k,将数组按k向右滚动。注意,要求在原数组基础上改动,而不是返回一个新的数组。
例如:
Input: [1,2,3,4,5,6,7] and 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]
思路及解法
法1.首先想到的是建立一个新的数组,将新数组按要求进行组装,数组的下标肯定可以建立数学关心,具体是对数组的下标进行取余等操作,最后将新数组的值赋给原数组。
法2.我们应该想到不管k是多少,数组里的每一个数都是要调整位置,也就是调整次数就是len(nums),也就是我们应该对调整次数进行计数,用于终止调整。对于k,可以理解为一个元素的移动总步长。这样,我们每次讲一个元素移动k位,到达它的最终位置,当然,这时候应该有一个临时变量用来存储这个最终位置上的元素。
我们参照下面这张图进行考虑。从这个情况可以看出,我们应该想的是k的取值能不能使得一次遍历完所有元素,图中这种情况是2次遍历完的。最简单的情况,k的取值刚好可以使得一次遍历完成,那么我们就按照上面说的方法修改数组就好了。
当k不能使一次遍历完时,就像下面这张图,我们能找到一个规律就是每一次遍历的结束标志是,返回到遍历的起点。我们也把这个规律作为一次遍历的终止条件。下一个遍历的起点就是上一次起点(也是终点)的下一个元素。这样一直循环遍历下去,直到总的遍历或者调整次数到达len(nums)
所以,整体的思路是这样的:
- 第i个数按步长k开始调整,第(i+k)数调整为第i个数的数值,同时1个临时变量存储第(i+k)个数的数值,一个临时变量存储第i个数值,一个用来传递数值,另一个用来储存数值用于下次的调整,另一个临时变量储存起点下标i
- 循环执行上述步骤,直到循环回到第i个数,一次子遍历结束
- 从第i+1个数开始下一次循环遍历,步骤如上述过程
- 在整个过程中,设置一个计数变量,当调整次数达到len(nums)时,表示所有元素调整完成,结束整个过程
代码
时间复杂度O(n)
空间复杂度O(n):因为一个新的大小为n的数组被使用
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: void Do not return anything, modify nums in-place instead.
"""
lens = len(nums)
k = k % lens
new_nums = [0] * lens
for i in range(lens):
new_nums[(i+k) % lens] = nums[i]
for i in range(lens):
nums[i] = new_nums[i]//LeetCode的oj是要写成单个值赋值的形式的,
//但是在编译器里可以两个list直接赋值,nums=new_nums
时间复杂度O(n)
空间复杂度O(1)
class Solution(object):
def rotate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: void Do not return anything, modify nums in-place instead.
"""
k %= len(nums)
count = 0
for i in range(len(nums)):
start_num = nums[i]
current = i
while 1:
next = (current + k) % len(nums)
tmp = nums[next]
nums[next] = start_num
start_num = tmp
current = next
count += 1
if next == i:
break
if count == len(nums):
break