Python List Rotate: 方法汇总

问题描述

给定一个python的list和一个正整数k,考虑将数组内的元素向右shiftk个位置(感觉用shift表示比较丝滑一些,其实类似于循环移位操作)。
e.g.

list_to_be_shifted=[1,2,3,4,5,6,7]
bitnum = 3
shift(list)
>>> list
[5, 6, 7, 1, 2, 3, 4]

问题本身的解决方案很多,但是题目要求使用空间复杂度为O(1)来实现,也就是利用原数组就地正法,这样一来对题目就多了不少限制。

开干

解法一

最直接的办法当然就是直接开干一波带走,你让我移k个位置,那我就一个个来呗,看谁先把谁送走了(这玩笑开不得,毕竟它只是一堆破 铜 烂 铁,Markdown不需要引号)。所以干法如下:

def shift(self, nums: list, k: int) -> None:
    """
    Do not return anything, modify nums in-place instead.
    """
    while k > 0:
        temp = nums[-1]
        for i in range(len(nums) - 1):
            nums[len(nums) - 1 - i] = nums[len(nums) - 2 - i]
        nums[0] = temp
        k = k - 1

值得注意的一点是,当数组长度len(nums)<k时,我们并不需要老老实实移动k次,将k直接对len(nums)取模即可,因此上面可以加上一句

k = k % len(nums)

鲁迅先生说过(好吧其实不是他说的):只要是循环结构我们都可以轻易地把它变成递归。但是在这里使用递归的话其实增加了堆栈开销,并不满足要求的空间复杂度,这里只是给一个思路:

def shift_recursion(self, nums: list, k: int) -> None:
    """
    Do not return anything, modify nums in-place instead.
    """
    k = k % len(nums)
    
    if k > 0:
        temp = nums[-1]
        for i in range(len(nums) - 1):
            nums[len(nums) - 1 - i] = nums[len(nums) - 2 - i]
        nums[0] = temp
        self.rotate_recursion(nums, k - 1)

这一做法本质上与循环结构没有大的区别,不再多说。

解法二,Reverse真香!

其实抛开一位位移动的想法,我们很容易就可以想到,为什么不一下子把后面待移动的k位直接放到前面去?这样子不是既省时又省力吗?好家伙,就这么干。稍加思索我们不难发现,所谓的这种移位操作,可以直接通过三次反转来实现!各位看官们,动一动小脑筋,问题就是这么简单(其实俺也没想到可以这么干,Leetcoder牛逼就完事了,自己画了一张丑图,大家将就着看看)。
在这里插入图片描述
可以看到,只需要简单的三次Reverse即可实现题目所要求的功能,可以说是大道至简,具体的python实现如下:

def reverse(self, array: list, begin: int, end: int) -> None:
    while begin < end:
        temp = array[end]
        array[end] = array[begin]
        array[begin] = temp
        begin += 1
        end -= 1


def shift_reverse(self, nums: list, k: int) -> None:
    if k == 0:
        return
    if k > len(nums):
        k = k % len(nums)
    
    nums.reverse()
    self.reverse(nums, 0, k - 1)
    self.reverse(nums, k, len(nums) - 1)

以上代码可以完美实现所要求的功能,且时间复杂度大大降低(使用上面逐个移位的方法对于大型的输入数组是会timeout的…大家注意了)。

解法三,充分利用Python特性

对于Python的list对象,负索引是一个创造性的发明(反正俺在以前学过的语言里面没见过,暂且认为它是具有创造性的叭,有问题提请大家指正!),这样一来,本身我就可以把数组的一个位置当做数组的头部,对数组进行重排列,这正是我们这一问题的本源!其实所谓的旋转,不过是换了数组的起始位置,旋转两位,其实就是从 -2位开始当做数组头,一直到-3位到达数组尾(当然这里的 -3也就是 +(len(nums) - k)),这是我们重构数组时索引结束的位置,那么使用列表生成式直接构建旋转后的数组的两种方法如下:

# method1
# Actually for python, we can use list generator and negative index
def rotate_generator(self, nums: list, k: int) -> None:
    nums[:] = nums[-k: len(nums)] + nums[0: -k]
# method2
def rotate_generator_new(self, nums: list, k: int) -> None:
    nums[:] = [nums[i] for i in range(- (k % len(nums)), len(nums) - (k % len(nums)))]

关于上述两种方法是否满足空间复杂度为 **O(1)**的要求,还请大家自行理解(就我个人的实验结果来看,方法一在旋转前后,nums指针的值未发生变化,至少说没有开辟新的堆内存空间,但是我觉得它不是空间复杂度为O(1)的实现方法,如有错误还请指正)。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中的List是一种非常常用的数据结构,它可以存储多个元素,并且可以进行各种操作。下面是一些常用的Python List操作方法汇总: 1.创建List: 可以使用方括号和逗号来创建一个List,例如: my_list = [1, 2, 3, 4, 5] 2.访问List元素: 可以通过索引来访问List中的元素,索引从0开始,例如: print(my_list[0]) # 输出1 3.修改List元素: 可以通过索引来修改List中的元素,例如: my_list[0] = 10 4.添加元素到List末尾: 可以使用append()方法来将元素添加到List的末尾,例如: my_list.append(6) 5.在指定位置插入元素: 可以使用insert()方法来在指定的位置插入元素,例如: my_list.insert(0, 0) 6.删除List中的元素: 可以使用remove()方法来删除List中的指定元素,例如: my_list.remove(5) 7.删除List中指定位置的元素: 可以使用del关键字或pop()方法来删除List中指定位置的元素,例如: del my_list[0] my_list.pop(0) 8.获取List的长度: 可以使用len()函数来获取List的长度,例如: length = len(my_list) 9.判断元素是否在List中: 可以使用in关键字来判断一个元素是否在List中,例如: if 6 in my_list: print("6在List中") 10.对List进行排序: 可以使用sort()方法List进行排序,例如: my_list.sort() 这些是一些常用的Python List操作方法,通过这些方法可以方便地操作List中的元素,提高编程的效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值