LeetCode #189 Rotate Array 数组 双变量 双指针
Description
Given an array, rotate the array to the right by k steps, where k is non-negative.
Example 1:
Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
Example 2:
Input: [-1,-100,3,99] and k = 2
Output: [3,99,-1,-100]
Explanation:
rotate 1 steps to the right: [99,-1,-100,3]
rotate 2 steps to the right: [3,99,-1,-100]
Note:
- Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.
- Could you do it in-place with O(1) extra space?
思路
解法一
拷贝一份源数组,以便在覆盖 nums
里的元素之后能够检索到该位置的旧值是什么,从而在下次更新 nums
时使用该旧值。
算法只需要 nums.size()
次更新操作,所以时间复杂度为 O(n)
;拷贝了一份数组,空间复杂度 O(n)
耗时16ms, ranking 80%
class Solution {
public:
void rotate(vector<int>& nums, int k) {
if (nums.empty()) return;
k = k % nums.size();
if (!k) return;
vector<int> backup = nums;
for (int i = 0; i < nums.size(); ++i) {
int next_idx = abs(i + k) % (nums.size());
nums[next_idx] = backup[i];
}
}
};
解法二
如果只观察间隔为 k
的元素的更新操作,比如 [1 2 3 4 5], k = 2
的话,只看 [1 3 5]
这三个位置的更新操作,那么在每次更新操作中,真正被用到的数据只有上一次被覆盖元素的值与索引,比如更新 3
时,我们用到了值 1
和索引 0
。因此可以利用双变量、双索引保存旧值与其位置,从而对解法一进行优化。
额外需要注意的是,由于解法二是 pick 出了间隔为 k
的元素,那么就可能会漏掉另一部分的元素,比如上一段话中的 [2 4]
就被忽略了,因为 k = 2
时,指针永远在 [1 3 5]
这三个数据之间循环。因此,需要再加入一个保存起始位置的索引start_idx
,当指针等于start_idx
时, 说明当前更新操作陷入局部数据而死循环了,需要将start_idx
与当前指针都自增,从而脱离死循环。
算法最终会对数组的每个位置都执行一次更新操作,所以总共执行 nums.size()
次更新操作,时间复杂度为 O(n)
;用了五个临时变量保存算法必要的信息,空间复杂度 O(1)
耗时16ms, ranking 80%
class Solution {
public:
void rotate(vector<int>& nums, int k) {
if (nums.empty()) return;
k = k % nums.size();
if (!k) return;
int idx = 0;
int start_idx = idx; // mark starting point
int prev = INT_MAX;
int cur = nums[idx];
int update_cnt = nums.size(); // only update size() times
while (update_cnt > 0) {
int next_idx = abs(idx + k) % (nums.size());
prev = cur;
cur = nums[next_idx];
nums[next_idx] = prev;
idx = next_idx;
// avoid endless loop caused by even k
if (idx == start_idx) {
++start_idx;
idx = start_idx;
cur = nums[idx];
}
--update_cnt;
}
}
};
参考
- 《[LeetCode] 189. Rotate Array 旋转数组》:https://www.cnblogs.com/grandyang/p/4298711.html
————全心全意投入,拒绝画地为牢