前言
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: [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:
输入: [-1,-100,3,99] 和 k = 2输出: [3,99,-1,-100]解释:向右旋转 1 步: [99,-1,-100,3]向右旋转 2 步: [3,99,-1,-100]
说明:
- 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
- 要求使用空间复杂度为 O(1) 的原地算法。
解决方案
提示
在解题之前,我们首先要确定一些异常情况,比如数组的长度为0,以及旋转的长度大于数组长度的情况。
其中如果旋转的长度大于数组
方案一 :利用额外的数组,然后进行旋转,空间复杂度o(n),时间复杂度o(n)
解题思路:将原来的数组进行备份,然后将数组的赋值按照传入的参数分为两部分,左边为原来分割的右部分;右边为分割的左部分,思路比较顺畅简单。需要注意的是:当传入的旋转度为len的时候相当于不旋转,当旋转度大于len的时候,和k-len的效果是相同的(len为数组长度)。
* @param {number[]} nums* @param {number} k* @return {void} Do not return anything, modify nums in-place instead.*/var rotate = function(nums, k) {let len = nums.lengthif(len ===0 || k ===0 || k===len ){return}if(k>len){k=k-len}let numsCp = [...nums]for(let i=0;i<len;i++){if(k>i){nums[i] = numsCp[(len-k+i)%len]}else{nums[i] = numsCp[i-k]}}};
方案二 :每次移动一个元素,将其他元素后移动,移动k次,空间复杂度o(1),时间复杂度o(n^2)
var rotate = function(nums, k) {let len = nums.lengthif(!k || k===len){return}if(k>len){k=k-len}for(let i =0 ;i<k;i++){let temp = nums[len-1]for(let j=len-1;j>0;j--){nums[j] = nums[j-1]}nums[0] =temp}};
方案三 :数组旋转看成分割后数组的翻转,然后再整体数组翻转,空间复杂度o(1),时间复杂度o(3n)
var rotate = function(nums, k) {let len = nums.lengthif(!k || k===len){return}if(k>len){k=k-len}let reverse = (arr,i,k)=>{if(k==1) returnfor(let j=0;j<Math.floor(k/2);j++){let temp =arr[i+k-j-1]arr[i+k-j-1] = arr[i+j]arr[i+j] = temp}}reverse(nums,0,len-k)reverse(nums,len-k,k)reverse(nums,0,len)};
