189. 旋转数组(简单)- LeetCode

题目描述

在这里插入图片描述

自己解法

解法一 - 暴力求解

直接原地移动数组,时间复杂度 O ( n 2 ) O(n^2) O(n2),空间复杂度 O ( 1 ) O(1) O(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(length-k,length):
            for m in range(i-1,i-length+k-1,-1):
                nums[m],nums[m+1] = nums[m+1],nums[m]

运行结果,超出时间限制:
在这里插入图片描述
输入数组的长度为2000,算法的复杂度为 O ( n 2 ) O(n^2) O(n2),超时在意料之中。

解法二 - 分治法

我们首先考虑什么情况下移动数组不会改变数组本身,有两种情况(分治法的临界条件):

  • 数组长度为1,不管移动多少位,数组不变
  • 数组长度与移动位数刚好一致,移动后数组不变

本题分治法的思想是不断交换划分子数组,直到达到临界条件,

假设输入数组为[1,2,3,4,5,6,7],移动位数k=3,如下图所示:
在这里插入图片描述
由题意可知,是想让原数组向右移动3位,第一步先把[5,6,7]三个元素移动到最终位置上,即与[1,2,3]逐个交换:

在这里插入图片描述

至此,虚线左侧的数组已经完成移动,但是虚线右侧的数组似乎已经乱了。关键的地方来了,通过观察得知,虚线右侧的数组[4,1,2,3]其实是由[1,2,3,4]向左移动3位(题目中k=3)得出的。

在这里插入图片描述
第一步将[5,6,7]移动3位,交换到最终位置上,此时虚线左侧的数组不用考虑了。后果是虚线右侧的子数组向移动了3位,为了抵消这一影响,需要将虚线右侧的子数组向右平移3位,交换位置,也就是重复第一步的操作。切记,虚线左侧的数组已经可以不用管它了。结果为:
在这里插入图片描述
这时,算法来到了终止条件之一:虚线右侧的子数组长度为1,不管对子数组怎么移动,子数组本身都不会变,算法结束,得到最终的数组就是[5,6,7,1,2,3,4]

在这里插入图片描述
下面演示第二种终止条件,输入数组为[1,2,3,4]k=2
在这里插入图片描述
第一步后,虚线右侧的子数组实际上向左平移了2位,但是由于子数组长度和平移位数一致,所以数组不变,到达终止条件。

代码如下:

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
        childLength = len(nums) # 子数组长度
        childStart = 0 #子数组起始下标
        while True:
            if childLength == 1 or k == 0: # 终止条件
                break
            temp = 0
            for i in range(length-k,length):
                nums[i],nums[childStart+temp] = nums[childStart+temp],nums[i]
                temp += 1
            childLength -= k
            childStart += k
            k %= childLength

算法复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)。最坏的情况下是k=1的情况,需要逐个交换元素,执行结果:

在这里插入图片描述

官方解答

地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值