题目描述
思路
这个题要求原地旋转,即交换这些数字的位置。那么只需要找到每个数字旋转后的所在位置(nextIndex)即可
数字的当前的位置用curIndex标识
数组长度 n
旋转距离 k
公式:
nextIndex = (curIndex+k) % n;
那么首先想到的就是对这个数组进行依次迭代,将迭代过程中的数字移动到对应位置
那么自然而然就会产生一个问题,目标位置原来的值就被替换掉了。
如果我们将目标位置原来的值保存下来,这样就会需要O(n)的额外空间,与题意不符
下面举个例子:
nums = [0,1,2,3,4,5,6,7]
k = 3;
根据上面的思路,为每个数字找到对应的位置
改变上面迭代的思路,换个方式:
找到0的下一个位置3后,继续找3的下一个位置,以此类推
这样就解决了空间复杂度O(1)的要求
这样这个数组的移动过程是这样的
0—>3
3—>6
6—>2
2—>5
5—>1
1—>4
4—>0
可以发现,所有的数字都找到了对应的位置
并且最后一个数字 4 移动到了最开始的 0 的位置
但是其实还有一个逻辑错误
假设
nums = {1,2,3,4,5,6}
k = 2;
如果按照上面的思路移动,只能移动1,3,5这三个数字
似乎是由奇偶数影响的
但其实本质上并不是
这是由 k 和 n 的最大公因数决定的
假设 k 和 n 的最大公因数是 x
那么我们要进行 x 次轮循环 进行上述算法
代码如下:
class Solution {
public void rotate(int[] nums, int k) {
//空间复杂度:O(1)
int n = nums.length;
if(k%n == 0) return;
int a = n%k;//
int c = 0;
int x = gcd(n,k);//循环的次数
while(c != x){
int curIndex = c;//目前要移动的位置
int tempIndex = (curIndex+k)%n;//移动的目标位置
int next = nums[tempIndex];//移动目标位置的值保存一下
nums[tempIndex] = nums[curIndex];//将目标位置的值替换掉
curIndex = tempIndex;
int temp;
while(curIndex != c){
tempIndex = (curIndex+k)%n;
temp = nums[tempIndex];
nums[tempIndex] = next;
next = temp;
curIndex = tempIndex;
}
c++;
}
}
private static int gcd(int a, int b) {
while (a != b) {
if(a>b)a-=b;
else b-=a;
}
return a;
}
}
关于题目要求说三种方式解决,我还没想出来,以后再说(大概率没有以后了)