吐槽
今天无聊刷这道题发现,,,不审题很尴尬唉,不然老过不了
题目
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 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) 的原地算法。
思路
这道题我一上手就想到用取余什么的,重新建个数组,然后取余赋值,返回这个新建的数组
然后,就发现这个网站上面自己的代码放在上面测试时候,老是有问题,然后我还提交以为是网站问题
下面就是代码233,很简单
public int[] rotate(int[] nums, int k) {
int[] result = new int[nums.length];
for (int i = 0;i < nums.length;i++){
result[(i+k) % nums.length] = nums[i];
}
return result;
}
之所以错误的原因很简单,因题目的要求是要求使用空间复杂度为 O(1) 的原地算法。
//估计测试网站看到你申请空间时候,测试这块就有问题了,很尴尬唉
所以,我们换种思路,把这个取余的想法进化一下,让其不用其他辅助数组就好了
我们每次在原数组处理的时候,将一个数组元素放到另外一个数组元素的位置,我们要放的元素处理了,但是原来位置的元素怎么办,我们也需要将这块处理下唉
比如:将下标为i的元素放在下标i+k处,再将下标i+k处的元素放置在正确位置
举个例子
现在这个数组就是 1 2 3 4 5 6 k =2
第一次时候 1 向右2个位置 跑到3的位置上
3 只好也右2个位置 把5的位置占了
5 向右也动两个位置 又因为循环取余出来 现在把1之前的位置占了
然后这一轮结束了,因为1元素的移动,3元素和5元素也要放到相应的位置上
然后进行下一轮
代码
public void rotate1(int nums[],int k){
if (k % nums.length == 0 || nums.length == 1){
return;
}
int count = 0;
k = k % nums.length;
for(int start = 0;count < nums.length;start++){
int current = start;
int p = nums[start];
do {
int next = (current + k)%nums.length;//取余操作别忘了
int temp = nums[next];
nums[next] = p;//把移动的坑位占了
p = temp;
count++;
current = next;//看下坑位元素也要找他的新坑位
}while (current != start);//把循环开始那个元素的坑占了,一轮循环就结束了
}
}