链接:https://leetcode-cn.com/problems/rotate-array
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
说明:
尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
要求使用空间复杂度为 O(1) 的 原地 算法。
思路一:
两次反转, 先反转整个,然后依次反转[0, k), [k, n)
时间复杂度:O(n) 。
缺点: n个元素被反转了总共 2次。
空间复杂度:O(1) 。 没有使用额外的空间。
void rotate(vector<int>& nums, int k) {
if (nums.size() < 2)
return;
if (k >= nums.size())
k = k % nums.size();
if (k==0)
return;
std::reverse(nums.begin(), nums.end());
std::reverse(nums.begin(), nums.begin()+k);
std::reverse(nums.begin()+k, nums.end());
}
思路二:
思路一种每个元素经历了两次反转。为优化这个问题, 可以先保存后K个元素, 然后将前N-k个元素向后移动K位, 再把保存的K个元素移到开头
时间复杂度: O(n)
空间复杂度: O(k)
void rotate(vector<int>& nums, int k) {
int len = nums.size();
int i = k % len;
// 保存后K个元素
for (int j = i; j > 0; j--) {
nums.push_back(nums[len-j]);
}
//将前N-K个元素向后移动K位
for (int j = len - 1; j >= i; j--) {
nums[j] =nums[j-i];
}
//将后K个元素放到开头
for (int j = 0; j < i; j++) {
nums[j] = nums[len+j];
}
//删除刚刚保存的K个元素
nums.erase(nums.begin()+len, nums.end());
}
思路三:
如果我们直接把每一个数字放到它最后的位置,但这样的后果是遗失原来的元素。因此,我们需要把被替换的数字保存在变量 temptemp 里面。然后,我们将被替换数字(temptemp)放到它正确的位置,并继续这个过程n次。
当然可能经过若干次过后, 回到起点, 所以如果回到起点就从下一个位置开始。
时间复杂度: O(n)
空间复杂度: O(1)
void rotate(vector<int>& nums, int k) {
int count = 0;
int current, next;
int preValue, postValue;
int len = nums.size();
k %= len;
for (int start = 0; count < len; start++) {
current = start;
preValue = nums[start];
do {
next = (current + k) % len;
postValue = nums[next];
nums[next] = preValue;
count++;
current = next;
preValue = postValue;
} while (current != start);
}
}
本文详细介绍了在LeetCode上解决数组旋转问题的三种不同算法,包括两次反转法、优化后的元素移动法以及循环替换法。每种方法都附有详细的步骤解析和C++代码实现,旨在帮助读者理解并掌握如何在不使用额外空间的情况下,高效地完成数组元素的旋转操作。
1082

被折叠的 条评论
为什么被折叠?



