旋转数组
1.问题描述
给定一个数组,将数组中的元素向右移动 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) 的 原地 算法。
2.求解
暴力法
- 每次向后旋转1位,旋转k次
public void rotate(int[] nums, int k) {
for(int i = 0; i < k; i++){
roateNums(nums);
}
}
void roateNums(int[] nums){
int temp;
int pre = nums[nums.length - 1];
for(int i = 0; i < nums.length; i++){
temp = nums[i];
nums[i] = pre;
pre = temp;
}
}
使用环状替换
-
把一个在
i位置上元素向后旋转k个元素,那么它的位置应该为next = (i + k) % length拿到一个元素,找到它的位置,然后拿到被替换的元素,再找它的位置,一直替换下去,代码如下
代码如下
while(next != current){ next = (current + k) % len; int temp = nums[next]; nums[next] = prev; prev = temp; current = next; count++; } -
看上去很美好,一直这样轮换不就可以了吗,但是这样仅仅适用于
k和length的最大公约数为1的情况,当不为1时,例如n=24, k=14时, 其最大公约数为2, 这一个替换只能替换一部分的元素,剩下的一部分元素一直不会被移动。 -
因此我们需要做一个判断,判断什么呢,对于n个元素,需要移动n次就够了,判断移动次数是否到n,如果为到n的时候
while循环结束了,说明这些元素是一个循环,我们应该换一个元素,再进行移位,直至移动次数到n次结束
代码如下
public void rotate(int[] nums, int k) {
int len = nums.length;
int count = 0;
for(int start = 0; count < len; start++){
int current = start;
int prev = nums[start];
do{
int next = (current + k) % len;
int temp = nums[next];
nums[next] = prev;
prev = temp;
current = next;
count++;
}while(start != current);
}
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)

浙公网安备 33010602011771号