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