算法- 数组K位轮转

100 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第24天,点击查看活动详情

题目描述:

给定一个数组,将数组中的元素向右轮转 K 个位置,其中 K 是非负数。

思路分析:

方法1: 通过使用一个临时数组,将轮转后的值存到新数组的新位置。这就和我们使用临时变量来暂时存储一样的道理。但是注意数组的临界,因为如果数组的长度超过最大的长度时需回到数组首位继续计算。

如nums = [-1,-100,3,99], k = 2 其中,3 在第i = 2 位,位移 k= 2位,则应该在 第 i = 4位,但是数组的长度是length = 4,轮转到i= 4时应该转到 i= 0位。所以临界条件时 i>=4 时,轮转后的位置应该是 i-length。但是如果数组只有一个元素,或者说数组内元素少于要乱转的位置数,以上就无法满足,所以需要使用(i + k) % length来计算轮转后的位置。

方法2: 以上使用了一个临时数组,如果在原数组上如何解决呢? 如果不使用数组的话,就是只在原数组上直接操作的话,可以是使用依次反转的方式进行操作,比如第一次全部反转就会将第一位转到最后一位,然后再反转前 K个,最后再将剩余的都反转,其实整个过程就是最后的结果:

原数组:【-1,100,3,99】

全部反转:【99,3,100,-1】

反转前 2个:【3,99,100,-1】

再反转剩余的:【3,99,-1,100】

就得到最终结果了。

代码实现

使用临时数组实现

var rotate = function(nums, k) {
    var temps =[];
    for(var i=0;i<nums.length;i++){
        temps[(i+k)%nums.length] = nums[i];
    }
​
     for(var i=0;i<nums.length;i++){
        nums[i] = temps[i];
    }
};

要求空间复杂度为 O(1)的实现

var rotate = function(nums, k) {
  int leng = nums.length;
  k % = leng
  reverse(nums,0, leng-1)
  reverse(nums,0, k-1)
  reverse(nums,k, leng-1)
}
​
function reverse(nums, start, end){
  while(start<end){
    let temp = nums[start];
    nums[start++] = nums[end]
    nums[end--] = temp;
  }
}