189. Rotate Array

LeetCode 189题

问题描述:

Given an array, rotate the array to the right by k steps, where k is non-negative.

Example 1:

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]

Example 2:

Input: [-1,-100,3,99] and 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:

  • Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
  • Could you do it in-place with O(1) extra space?
class Solution:
    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
        for i in range(0, k):
            tmp = nums[lens - 1]
            for j in range(lens - 1, - 1, -1):
                nums[j] = nums[j - 1]
            nums[0] = tmp

这是第一次给出的解法。根据题目意思很容易知道当k==len(nums)时,数组不变,即只需要移动k = k % len(nums)即可,后面就是循环移动数组了。然而,由于循环次数太多,当数组过大时很容易超时,在这个解法中需要移动 k * (n - 1)次,需要尽可能地减少移动次数。

如果用一个额外的数组,那么只需要遍历一次就可以了。但是这样就没什么难度了。

经过观察发现向右循环移动k次,实际上等价于向左循环移动(n - k)次,可以尝试从两者选择移动次数最少的一种。但是在最坏的情况下,也就是k = n / 2时,仍需要(n / 2)* (n - 1)次移动,还是不够。  

实际上,移动前数据的下标与移动后数据的下标之间的关系是确定的,可计算的,其关系为可表示为idxAfter = (idxBefore + k) % len(nums)。

class Solution:
    def rotate(self, nums, k):
        lens = len(nums)
        k = k % lens
        count = 0
        for i in range(0, k):
            if count == lens:
                break
            tmp = nums[(i + k) % lens]
            nums[(i + k) % lens] = nums[i]
            j = (i + k) % lens
            count += 1
            while j != i:
                tmp2 = nums[(j + k) % lens]
                nums[(j + k) % lens], tmp = tmp, tmp2
                j = (j + k) % lens
                count += 1

从下标0开始,移动数组内元素。移动时会覆盖掉下一个位置的元素,因此用一个临时变量先将其存起来。另外由于取余的效果,下标的变化是循环的,因此以循环一轮作为while的退出条件(没有do while语句,因此在进入while之前,先移动一次)。而for语句是循环的次数,有两种情况,一种是只循环一次,遍历数组,第二种是循环k次,每次遍历n/k个元素,但不论何种循环方式,其访问的元素个数均为len(nums)个。以count记录已遍历的元素个数,当count == lens时,即移动结束,退出for循环。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值