轮转数组
- 1、题目描述
- 2、解答思路
- 2.1、辅助数组
- 2.2、原地反转
1、题目描述
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
2、解答思路
2.1、辅助数组
如果我们在原数组上通过覆盖元素会导致部分元素的丢失,因此这里使用额外的数组用来保存轮转后的数组。由题意可得,长度为m的数组,轮转 k 后,数组元素下标 index 和之前的下标 i 关系是 index = (i+k) % m。得到上述关系即可解答问题。
class Solution {
public void rotate(int[] nums, int k) {
int m = nums.length;
int[] ans = new int[m];
for(int i=0; i<m; i++){
// 求解当前下标元素复制到另一个数组的下标
int index = (i+k)%m;
ans[index] = nums[i];
}
// 将ans的元素从下标0开始复制m个元素到数组nums中
System.arraycopy(ans, 0, nums, 0, m);
}
}
- 将数组ans复制到nums时出现的错误:我利用 nums = Arrays.copyOfRange(ans, 0, m+1) 来复制时得到的结果是错误的,这是因为 Arrays.copyOfRange()
创建并返回了一个新的数组,因此赋值后的nums和之前的nums已经不是同一个数组了,而题目要求的是原来的nums轮转k个位置,因此出现了结果错误的情况。- 时间复杂度: O(n),其中 n 为数组的长度。
- 空间复杂度: O(n),额外增加了长度为n的辅助数组。
2.2、原地反转
根据题意可得到结论:将长度为n的数组向右轮转k个位置时,首先反转整个数组,然后反转前k的元素,最后反转n-k个元素,得到的结果即为最终结果,如下图所示。
class Solution {
public void rotate(int[] nums, int k) {
int n = nums.length;
k %= n; // 由于 k 可能大于 n ,因此轮转 k 次等于轮转 k%n 次
reverse(nums, 0, n - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, n - 1);
}
// 将数组 nums下标 i 到 j 的元素翻转
private void reverse(int[] nums, int i, int j) {
while (i < j) {
int temp = nums[i];
nums[i++] = nums[j];
nums[j--] = temp;
}
}
}
- 时间复杂度:O(n),其中 n 是 nums 的长度。
- 空间复杂度:O(1),原地反转的方法不需要辅助数组,因此空间复杂度为O(1)。