题目:
给定一个整数数组 nums,将数组中的元素向右轮转 k个位置,其中 k是非负数。
示例 1:
输入: nums = [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:
输入: nums = [-1,-100,3,99], k = 2
输出: [3,99,-1,-100]
解释:向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
提示:
1 <= nums.length <= 10^5-2^31 <= nums[i] <= 2^31 - 10 <= k <= 10^5
题解:
观察旋转后的数组特点:
-
原数组
[1,2,3,4,5,6,7]向右旋转 3 步后得到[5,6,7,1,2,3,4]。 -
旋转结果可以看作:原数组的后 k 个元素移到前面,前 n-k 个元素移到后面。
利用数组**反转(reverse)**可以在 O(1) 额外空间内实现:
-
反转整个数组 → 后 k 个元素跑到了前 k 个位置,但顺序是反的。
-
反转前 k 个元素 → 将前 k 个元素恢复正确顺序。
-
反转后 n-k 个元素 → 将剩余元素恢复正确顺序。
答案:
cpp
class Solution {
public:
void rotate(vector<int>& nums, int k) {
if(nums.size()==0) return;
k=k%nums.size();
if(k==0) return;
//reverse(first, last) 反转的是 [first, last) 区间,左闭右开,即包含 first 指向的元素,不包含 last 指向的元素。
//反转整个数组
reverse(nums.begin(),nums.end());
//反转前 k 个元素
reverse(nums.begin(),nums.begin()+k);
//反转后 n-k 个元素
reverse(nums.begin()+k,nums.end());
}
};
要点:
- 反转区间 :C++ 标准库 reverse(first, last) 反转的是**[first, last)** 左闭右开区间。
- k 可能大于数组长度 :当 k 大于数组长度时,向右轮转 n 步(n 为数组长度)会使数组完全回到原始状态。所以需执行 **k = k % nums.size()**来得到真正需要移动的步数。