leetcode 189.旋转数组

时间:2020-08-26 17:11:58   收藏:0   阅读:51

官方解题给出了四种解法。

第一种,暴力法,时间复杂度O(n*k)。

第二种,额外构建一个等大数组,将额外数组作为中介进行两次全数组的拷贝。时间代价为O(n)。空间代价也为O(n)。

第三种,环状替换,也是我自己实现的方法。时间代价O(n),空间代价O(1)。

如果我们直接把每一个数字放到它最后的位置,但这样的后果是遗失原来的元素。因此,我们需要把被替换的数字保存在变量temp 里面。然后,我们将被替换数字(temp)放到它正确的位置,并继续这个过程 n次, n是数组的长度。这是因为我们需要将数组里所有的元素都移动。但是,这种方法可能会有个问题,如果n%k==0,其中 k=k%n (因为如果 k 大于 n ,移动 k 次实际上相当于移动 k%n 次)。这种情况下,我们会发现在没有遍历所有数字的情况下回到出发数字。此时,我们应该从下一个数字开始再重复相同的过程。

实际上,形成的环数(我自己更愿意称为切片数)=数组长度n和移动距离k的最大公约数。从这一点出发,对每个环进行循环替换。

代码如下

 1 class Solution {
 2 public:
 3     void rotate(vector<int> &nums, int k) {
 4         int len = nums.size();
 5         k = k % len;
 6         if (k == 0)return;
 7         int l= gongyin(len, k);
 8         int p = len / l;//l个切片,每个切片p个元素
 9         for (int i = 0; i < l; ++i) {
10             for (int j = 0; j < p - 1; ++j) {
11                 swap(nums[i], nums[(i + (j + 1) * k) % len]);
12             }
13         }
14 
15     }
16 
17 private:
18     void swap(int &a, int &b) {
19         int temp;
20         temp = a;
21         a = b;
22         b = temp;
23     }
24 
25     int gongyin(int &a, int &b) {
26         int num1 = 0, num2 = 0, c = 0; //num1,num2作为计算时的变量,c作为中间变量
27         if (a >= b) {
28             num1 = a;
29             num2 = b;
30         } else {
31             num1 = b;
32             num2 = a;
33         }             //通过比较对num1和num2赋值,便于计算
34         while (num2 > 0) {
35             c = num1 % num2;
36             num1 = num2;
37             num2 = c;
38         }                  //辗转相除,num2=0时,num1=最大公因数
39         return num1;
40     }
41 
42 };

以上的数据位移我是用swap实现的,可能并不符合直观的感受,但是实际是可行的,如果按正常的思路循环替换,那么需要两个额外变量。这里我只用了一个额外变量。而且在时间上的代价应该是差不多的。。除非频繁的swap函数调用占了很多时间,具体没有试过。

最大公因数这个for循环的边界条件确实比较难想到,一个小技巧是可以用移动过的元素数count作为循环边界条件,那么就不需要计算最大公因数了。

 

第四种方法是使用反转。这就很巧妙了。

技术图片

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!