leetcode_189. 轮转数组
题目描述:
给定一个整数数组 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 <= 105
-231 <= nums[i] <= 231 - 1
0 <= k <= 105
题解–反转数组
如果把这道题当成简单的模拟器, 那情况就会变得比较复杂, 除非使用额外的空间, 将原数组复制一份, 然后循环执行nums[(i + k) %length]
, 这也不是不行, 只是稍显笨拙.
其实我们可以换个思路, 将原来的数组轮转其实可以用反转数组来实现
- 将数组整体反转
- 将数组
0~k-1
反转 - 将数组
k~length-1
反转
我们来证明一下, 假如我们要将下面这个数组轮转3个位置,
我们先将整个数组整体反转
紧接着反转前3个元素
在然后, 反转剩下的元素
看, 是不是很神奇, 我们就真的通过这种方式实现了数组轮转.
那原理是什么呢
数组轮转本来就可以看作是直接把数组右边的k
个元素直接截下来, 然后插到开头的位置, 但是由与我们这是数组, 不是链表, 不能只移动右边的k
个而不动其他的,
这时如果我们让整个数组整体反转, 然后再分别反转前k
个, 和后面length - k
个, 就等效于直接把后面k
个元素拆下来, 插到了开头.
Java
class Solution {
public void rotate(int[] nums, int k) {
int length = nums.length;
k = k % length;
reverse(nums, 0, length -1);
reverse(nums, 0, k - 1);
reverse(nums, k, length -1);
}
public void reverse(int nums[], int l, int r) {
while (l < r) {
nums[l] = nums[l] ^ nums[r] ^ (nums[r] = nums[l]);
l ++;
r --;
}
}
}
c++
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int length = nums.size();
k = k % length;
reverse(nums, 0, length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, length -1);
}
void reverse(vector<int>& nums, int l, int r) {
while ( l < r) {
//nums[l] = nums[l] ^ nums[r] ^ (nums[r] = nums[l]);
swap(nums[l], nums[r]);
l ++;
r --;
}
}
};