LeetCode(初级算法之数组)-旋转数组

这是刷LeetCode的第三天,原题地址

题目描述

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

示例一

输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1: [7,1,2,3,4,5,6]
向右旋转 2: [6,7,1,2,3,4,5]
向右旋转 3: [5,6,7,1,2,3,4]

示例二

输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]
解释: 
向右旋转 1: [99,-1,-100,3]
向右旋转 2: [3,99,-1,-100]

说明

  • 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
  • 要求使用空间复杂度为 O(1)原地 算法。

解题思路

这个题目说明了要采用原地算法,所以我们只能对当前数组进行操作,其实除了这个条件貌似没有其他的要求了。就是数组的循环移动。

第一种方法

我自己做的时候,是想到了一种双重循环的方法去解决这个问题。即移动一个尾数,就将数组中其他的元素均向后移一位,然后把尾数元素放在数组首位,循环往复直至完成。这种方法的思维比较简单,对于基本的也能实现,同时执行结果也会显示正确,但是这个方法对于此题来说会超时(见运行结果的第一种方法)。而我当前水平有限,只能想到这种方法,于是便去学习别人的思想与代码。

第二种方法

其实这种方法跟上面那种方法本质上是一样的,只是把我用来条件判断的条件改了一下循环条件。所以仍超时。
第一二种方法都成为暴力方法,其时间复杂度和空间复杂度如下:

  • 时间复杂度:O(n*k) 。每个元素都被移动 1 步(O(n)) k次(O(k))。
  • 空间复杂度:O(1)。没有额外空间被使用。

第三种方法

新增一个数组tem,将tem用来存放每个元素旋转后的正确位置上,即原本数组里下标为 i 的元素,将其放到 (i+k)%length 的位置,然后把tem中的元素拷贝到原数组中。

当时被原地更新限制了自己的思维,以为只能用一个数组,且只能在原数组上进行操作,所以当时受这种思维的限制,即只能想到第一种办法,代码简洁之后,也只能想到第二种办法。当看到官方题解中的这个解法的时候,其实我当时是很质疑的,因为还被困在那个思维中没走出来,一直觉得从头到尾都只能用一个数组。而题目的意思应该是将更新完后的结果存放到原数组中,这或许就是“原地更新”吧。又学到了一种思维以及方法!

  • 时间复杂度:O(n),两个并行的循环,每个都需要将数组遍历一遍,两个循环都是O(n)。
  • 空间复杂度:O(n),开辟了一个与原数组大小相等的数组。

运行结果

第一种方法

第一次运行结果
在这里插入图片描述
按照题目的意思是,当k值大于数组长度的时候,需要取余,令k = k mod len(nums).
于是根据这个要求,对代码进行修改,只要在循环前加上k = k % length即可。

但是却得到了如下运行结果:
在这里插入图片描述
超出时间限制了,说明双重循环不符合题目的要求,于是另寻他经。

第二种方法

与上述结果一样

第三种方法

在这里插入图片描述
可见这种方法是行得通的。但是在第一次运行的时候,我将tem定义为一个数组,因为里面没有任何元素,所以一开始报‘list assignment index out of range’,上网搜索原因,一个说是:

  • 列表超过限制
  • list[index]index超出范围
  • list是一个空的,没有一个元素,进行list[0]就会出现错误

虽然我觉得我没有像这种情况,但是将tem = []改为tem = {}后,成功运行了,且通过测试。

由于我当前的学识,只能想到上述方法,于是便去学习大佬们的做法。

源代码

第一种方法

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        length = len(nums)
        k = k % length
        for i in range(length):
            if k == 0:
                break
            rot = nums[length-1]
            for j in range(length-1, 0, -1):
                nums[j] = nums[j-1]

            nums[0] = rot
            k -= 1

第二种方法

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        length = len(nums)
        k = k % length
        for i in range(k):
            rot = nums[length - 1]
            for j in range(length):
                t = nums[j]
                nums[j] = rot
                rot = t

第三种方法

length = len(nums)
    tem = {}
    for i in range(length): 
        tem[(i+k) % length] = nums[i]
    for i in range(length):
        nums[i] = tem[i]

总结反思

这个时隔一个多月才发,本来列了提纲是有四种方法,但是搁置太久不太记得了,或许文章中也有错误没发现。以后得及时写及时总结,今日事今日毕,不拖沓。加油吧!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值