(leetcode 189)旋转数组(4种思路)

原题如下:
在这里插入图片描述参考官方题解链接,代码及本文理解为笔者手写。

方案1、n个数每个都后移1位,后移k次。

时间复杂度O(n*k),不太推荐。

方案2、使用额外n个空间,存储,按照next=(now+k)%len(nums),将now位置的值直接写到新数组的对应的位置,这样没有覆盖值得问题,但是不符合题目要求。

空间复杂度O(n),不太推荐。

方案3、每位跳k,直到所有位都跳k

过程如下:
从初始值开始,将0写到0+k位置上,临时原保存0+k位置的值;
临时保存的0+k原值写到0+2k的位置上,临时保存0+2k的值;

记录移动值的个数,当等于len(nums)时,终止循环。

这个思路存在一点缺陷,就是当走了一圈回到原地,
例如[5,6,7,8],k=2中,
第一次改变值后[5,6,5,8],tmp=7;当前位置为0,next位置为2;
第二次改变值后[7,6,5,8],tmp=5;当前位置为2,next位置为0;
第三次改变值后[5,6,5,8],tmp=7;当前位置为0,next位置为2;
第四次改变值后[7,6,5,8],tmp=5;当前位置为2,next位置为0;
这样,即便走够了len(nums)次循环,也没有走到下标为1和3的位置,这是因为又回到了原点,重复走了0,2位置。

因此,作为循环的补充,在每次更改值之前先判断是不是位于原起点start,如果不是,则继续;如果是,则start+=1,now+=1,tmp=lst[now]。
也就是说,如果起点相同,我们将循环整体后移一位,再次起点相同,我们再整体移动一位,直到更改了len(nums)个元素。

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        l=len(nums)
        if l<2:
            return
        k=k%l
        
        count=0
        start=0
        index=0
        a=nums[index]
        while count<l:
        	#如果新一轮回到了起点,整体后移
            if index==start:
                start=(start+1)%l
                index=(index+1)%l
                a=nums[index]
            nxt=(index+k)%l
            #b暂存nxt的值
            b=nums[nxt]
            nums[nxt]=a
            #将b赋值给a,a是下一轮需要替换进去的元素
            a=b
            index=nxt
            count+=1

方案4、旋转数组

分三步:

对于数组[1,2,3,4,5,6,7],k=21)整体反转,变[7,6,5,4,3,2,1]2)前k个反转[6,7,5,4,3,2,1]3)后n-k个反转,[6,7,1,2,3,4,5]

之所以这样想,笔者的想法是旋转是两个值之间的交换,不存在值覆盖的问题
另外,可以这样想,
(1)将一个数组分成两部分,前n-k位、后k位。
[1,2,3,4,5,6,7],分为[1,2,3,4,5]、[6,7]两部分
(2)这两部分内部一直是有序的,只需要两者相互换位置。
即最终应为:[6,7]、[1,2,3,4,5]
(3)要换位置,整体逆序后两部分都会在应该的位置上。只是因为整体逆序后内部顺序反了。
此时为[7,6]、[5,4,3,2,1]
(4)作为对(3)的修正,分别将两部分内部顺序反转即可。

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        if len(nums)<2:
            return
        k=k%len(nums)
        def reverse(lst,left,right):
            while left<right:
                lst[left],lst[right]=lst[right],lst[left]
                left+=1
                right-=1
        reverse(nums,0,len(nums)-1)
        reverse(nums,0,k-1)
        reverse(nums,k,len(nums)-1)

相比较来说,方案三较快一点,但是比较复杂,面试的时候可能会写不出来,方案4要直观的多,也没慢多少。
在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值