旋转数组

110 阅读1分钟

描述

一个数组A中存有 n 个整数,在不允许使用另外数组的前提下,将每个整数循环向右移 M( M >=0)个位置,即将A中的数据由(A0 A1 ……AN-1 )变换为(AN-M …… AN-1 A0 A1 ……AN-M-1 )(最后 M 个数循环移至最前面的 M 个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

数据范围:0<n≤1000<n≤100,0≤m≤10000≤m≤1000

进阶:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)

示例1

输入:

6,2,[1,2,3,4,5,6]

返回值:

[5,6,1,2,3,4]

示例2

输入:

4,0,[1,2,3,4]

返回值:

[1,2,3,4]

备注:

(1<=N<=100,M>=0)

解题思路:

该方法基于如下的事实:将数组的元素向右移动 k 次后,尾部 m mod n 个元素会移动至数组头部,其余元素向后移动 m mod n 个位置。

1、可以先将所有元素翻转,这样尾部的 m mod n 个元素就被移至数组头部,

2、然后再翻转 [0,m mod n−1] 区间的元素

3、 最后翻转[m mod n,n−1] 区间的元素即能得到最后的答案。

实例:
以 n=7,m=3 为例进行如下展示:

操作结果
原始数据【1,2,3,4,5,6,7】
翻转所有元素【7,6,5,4,3,2,1】
翻转 [0,m mod n −1] 区间的元素【5,6,7,4,3,2,1】
翻转 [m mod n, n −1] 区间的元素【5,6,7,1,2,3,4】

最后返回:【5,6,7,1,2,3,4】

    def solve(self , n , m , a ):
        # write code here
        m = m % n
        # 数组反转
        # 翻转全部
        self.reverse(a, 0, n - 1);
        # 再翻转 【0,m-1】
        self.reverse(a, 0, m - 1);
        # 再翻转 【m,n-1】
        self.reverse(a, m, n - 1);
        return a
        
    def reverse(self, nums, start, end):
        # 数组翻转
        while start < end :
            # 双指针遍历翻转
            temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start += 1;
            end -= 1;