189th 旋转数组
-
利用空间特性解题
例如
输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]我们会发现,答案数组前端的k个元素,恰好是原数组末端的k个元素。因此我们只需要把原数组拆分为两个数组:head(包含原数组的前nums.length-k个元素)与tail(包含原数组的末端k个元素),最后再整合到原数组即可。
需要注意的是
例如 [1,2]和k =3因为k > nums.length,因此不做修饰的话会导致出错。
我们会发现,当k == nums.length时,答案数据与原数组相同(相当于没有移动)。
因此,当 k > nums.length时,我们只需要移动k%nums.length个位置即可。
class Solution { public void rotate(int[] nums, int k) { if(nums.length == 0 || nums.length == 1) return; if(k > nums.length) k %= nums.length; int[] tail = new int[k]; int cnt = 0; for(int i = nums.length-k; i < nums.length; i++) tail[cnt++] = nums[i]; int[] head = new int[nums.length-k]; for(int i = 0; i < nums.length-k; i++) head[i] = nums[i]; for(int i = 0; i < k; i++) nums[i] = tail[i]; cnt = 0; for(int i = k; i < nums.length; i++) nums[i] = head[cnt++]; } }
-
暴力模拟法
根据题意,我们只需要把数组旋转k次即可(每次将最末尾的数字转移到最前面)。
class Solution { public void rotate(int[] nums, int k) { if(nums.length == 0 || nums.length == 1) return; for(int i = 0; i < k; i++) { int prime = nums[nums.length - 1]; for(int j = 0; j < nums.length; j++) { int t = nums[j]; nums[j] = prime; prime = t; } } } }
-
利用圈的特性解题
我们知道,要是用数组或顺序结构的链表去模拟一个环形,需要使用取余%运算。取余运算可以完美的将超出部分截断并作为新一环的初始。
因此,例如对于[1,2,3,4,5,6,7]且k=3,我们只需要看为每个元素均向右移三个位置即可,对于超出部分,利用取余运算将数组做成环状。
由于我们每次都需要在原有数据基础上进行运算,因此需要一个额外的数组空间。
class Solution { public void rotate(int[] nums, int k) { if(nums.length == 0 || nums.length == 1) return; int[] target = new int[nums.length]; for(int i = 0; i < nums.length; i++) { target[(i+k) % nums.length] = nums[i]; } for(int i = 0; i < nums.length; i++) { nums[i] = target[i]; } } }