旋转数组

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

示例 1:

输入:[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]

示例 2:

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

说明:

尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。

要求使用空间复杂度为 O(1) 的原地 算法。


先抛去问题,了解一下空间复杂度。

直接上百度百科


空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))。比如直接插入排序的时间复杂度是O(n^2),空间复杂度是O(1) 。而一般的递归算法就要有O(n)的空间复杂度了,因为每次递归都要存储返回信息。一个算法的优劣主要从算法的执行时间和所需要占用的存储空间两个方面衡量。

就是运行时占用存储空间的大小度量。


思考问题:

0123456

1234560

2345601

3456012


Do not return anything, modify nums in-place instead.

不要返回任何内容,而是在适当的位置修改nums。


看一下给的参数,一个是由整数组成的列表,还有个整数K表示旋转次数

首先想到切片方法,计算列表长度,以K为分界,[:len-k]+[:len-k]

后K位加前len-K位


编译器没问题。


提交不对,那就是还有问题,读题,要求空间复杂度为O(1)的原地算法,把我写的拆解开

a = nums[len(nums)-k:]      b = nums[:len(nums)-k]   nums = a + b

明显不是原地,或许是这个问题


查找资料时发现一个通过的切片方法

        nums[:] = nums[len(nums)-k:] + nums[:len(nums)-k]

   对比我写的,区别在于  nums   nums[;]


于是该讨论一下  [ : ]  的意义了

正常来讲,它代表切片,


对比一下区别,发现A[;]需要定义,



编译器结果相同,

[:] 在我以往的理解中表示切片操作,不加参数表示从头到尾都要,既然是操作那就要有操作对象,刚才写了个A,但是没有定义就是不存在操作,所以报错。

题目中传入一个列表,对其操作,有可切片操作对象就可以正常运行。但为什么这道题要写nums[:],nums缺不行



对nums赋值操作,

失败了


加上切片操作


成功了。想吧,猜是为啥好使了?

没想明白,百度看了一下别人的切片用法


# 在某个位置插入多个元素

>>> alist[3:3] = ['a','b','c']

>>> alist

[0, 1, 2, 'a', 'b', 'c', 3, 4, 5, 6, 7, 8, 9]

# 在开始位置之前插入多个元素

>>> alist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> alist[:0] = ['a','b','c']

>>> alist

['a', 'b', 'c', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 替换多个元素

>>> alist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> alist[0:3] = ['a','b','c']

>>> alist

['a', 'b', 'c', 3, 4, 5, 6, 7, 8, 9]

————————————————

版权声明:本文为CSDN博主「混沌鳄鱼」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/xpresslink/article/details/77727507


或许替换元素用法,替换与赋值之间有什么区别,或许是赋值,浅拷贝,深拷贝的问题


由于python中的变量都是采用的引用语义,数据结构可以包含基础数据类型,导致了在python中数据的存储是下图这种情况,每个变量中都存储了这个变量的地址,而不是值本身;对于复杂的数据结构来说,里面的存储的也只只是每个元素的地址而已。


变量的每一次初始化,都开辟了一个新的空间,将新内容的地址赋值给变量。两次都是a,但其内存地址发生了改变,a不是那个a了。


当对列表中的元素进行一些增删改的操作的时候,是不会影响到lst1列表本身对于整个列表地址的,只会改变其内部元素的地址引用。可是当我们对于一个列表重新初始化(赋值)的时候,就给lst1这个变量重新赋予了一个地址,覆盖了原本列表的地址,这个时候,lst1列表的内存id就发生了改变。上面这个道理用在所有复杂的数据类型中都是一样的。


或许这个就是问题的关键,nums =     是对一个列表初始化,nums的内存地址发生改变,nums不是那个nums了,但是nums[:] =          是对列表中元素操作,改变的是列表中元素的内存地址,nums的内存地址不变。它还是那个它。

卧槽,我去年就是这道题我用切片方法卡了我一周也没明白,我悟了,写这玩意还真有用。



创建一个列表a,给b赋值为a,那么b的内存地址指向的是a,对a中元素操作,a的内存地址不变,变的是a[0]的内存地址,我们对b没有任何操作,为什么b中元素改了,因为b还是指向a的内存地址,a的内存地址是什么,还是那个列表,其中元素变了但在内存地址上没变,计算机不会说谎,有什么就说什么,所以b[1]变成了1111.

这就是赋值,赋予的是内存地址。

浅拷贝:不管多么复杂的数据结构,浅拷贝都只会copy一层。


有A,B两个列表,其中B中包含有A,对B进行浅拷贝,得到C,无论对B或对C修改对另一方都无影响,但修改A会影响BC,对B产生影响是正常的,但C是B的拷贝,应该是一个全新的对象只有自身才能产生影响,但浅拷贝的特点是只拷贝一层,无论多么复杂,这里C中元素都是新的内存地址,但B的B[4]为A,A的内存地址是一个列表,不受列表中元素影响,所以当A中元素改变时,A的内存地址还是A,但内容不一定。

最保险的是深拷贝,无论多么复杂的数据结构,都要探索到底部,对所有创建新的内存地址。


赋值相当于我有你家的钥匙,你家就是我家。

浅拷贝相当于我在你家前面放一面镜子,我可以在镜子上画画,但不会影响带你家,但你家打开门搬运东西时镜子里的画面都会发生变化

深拷贝相当于我在你家走来走去,所有细节都不放过,然后自己找个地方弄个新的,跟你家从里到外一模一样,但是写的我名。


老子真是个天才,解释通了!

你可能感兴趣的:(旋转数组)