Q 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
进阶:
尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。 你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?
A 使用额外的数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution { public void rotate (int [] nums, int k) { int [] temp = new int [nums.length]; if (k<nums.length){ for (int i=0 ;i<k;i++){ temp[i] = nums[nums.length-k+i]; } System.arraycopy(nums, 0 , temp, k, nums.length-k); System.arraycopy(temp, 0 , nums, 0 , nums.length); }else if (k>nums.length&&nums.length!=1 ){ k=k%nums.length; for (int i=0 ;i<k;i++){ temp[i] = nums[nums.length-k+i]; } System.arraycopy(nums, 0 , temp, k, nums.length-k); System.arraycopy(temp, 0 , nums, 0 , nums.length); } } } class Solution { public void rotate (int [] nums, int k) { int n = nums.length; int [] newArr = new int [n]; for (int i = 0 ; i < n; ++i) { newArr[(i + k) % n] = nums[i]; } System.arraycopy(newArr, 0 , nums, 0 , n); } }
数组翻转 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public void rotate (int [] nums, int k) { k %= nums.length; reverse(nums, 0 , nums.length - 1 ); reverse(nums, 0 , k - 1 ); reverse(nums, k, nums.length - 1 ); } public void reverse (int [] nums, int start, int end) { while (start < end) { int temp = nums[start]; nums[start] = nums[end]; nums[end] = temp; start += 1 ; end -= 1 ; } } }
思路 该方法基于如下的事实:当我们将数组的元素向右移动 kk 次后,尾部 kmodn 个元素会移动至数组头部,其余元素向后移动 kmodn 个位置。 该方法为数组的翻转:可以先将所有元素翻转,这样尾部的 kmodn 个元素就被移至数组头部,然后再翻转 [0,kmodn−1] 区间的元素和 [kmodn,n−1] 区间的元素即能得到最后的答案。
1 2 3 4 5 6 7 nums = "----->-->"; k =3 result = "-->----->"; reverse "----->-->" we can get "<--<-----" reverse "<--" we can get "--><-----" reverse "<-----" we can get "-->----->" this visualization help me figure it out :)
时间复杂度:O(n),其中 n 为数组的长度。每个元素被翻转两次,一共 n 个元素,因此总时间复杂度为 O(2n)=O(n)。
空间复杂度:O(1)。
环状替换 官方解答最优解法 暂时没整明白