经常可以见到所谓的数组循环移位的问题,那么什么是数组的循环移位呢?数组的循环移位指的是这样一个过程。假设数组构成了一个链环,整个数组作为链环的一个部分存在,那么我们任取这个链环的一部分,可能超过这个数组的长度,也可能小于等于这个数组的长度。现在考虑我们所取的部分长度等于数组的长度,那么它可能是一个完整的链环的一节,但更多情况下,是某一个链环和它相邻链环的一部分。这样得到的部分实际上就是数组循环移位后得到的新数组。
获得数组的循环移位的过程可以理解为从一个链环中获取它的长度等于每一个链节的一部分
那么对原数组而言,数组循环移位的的方向也有左右之分。如果要求N个元素的数组循环右移K位,事实上是将原数组的后面K个元素转接到数组前面来。而在直观上,给人的感觉反而是截取的区域向左移动了K位。这只是一个相对运动的错觉而已。
如图,右移两位相对于矩形区域是左移了两位,反之亦然。
那么如何实现数组的循环移位呢?首先可能想到的就是一个一个地对每个元素进行操作。一般称之为暴力法。暴力法一般不在乎遍历多少次,只要能够达到目的,所以往往时间复杂度较高,但往往不会开辟新的额外空间。像这里如果我们希望对数组(对应python中的列表)[1, 2, 3, 4, 5, 6]循环右移两位,暴力法的思路大概是这样的:
考虑一下它的时间复杂度。
每实现一次移位,需要遍历整个数组的元素,所以暴力法的时间复杂度就是O(k*N),其中N为数组长度,k为循环位移的位数。如果这个k大于数组长度N,那么移动k次的效果实际上和移动(k%N)的效果是一样的。注意到这里的赋值一定是要按照从后往前的顺序,切不可反过来,导致数据的覆盖。
#如何对数组进行循环移位
#方法一:暴力法
def rightShift(arr, k):
lens = len(arr)
k = k % lens
while k != 0:
tmp = arr[lens-1]
i = 1
while i < len(arr):
arr[i] = arr[i-1]
i += 1
arr[0] = tmp
k -= 1
if __name__ == "__main__"