旋转数组


给定一个数组,将数组中的元素向右移动 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]

方法:

/**
* @param {number[]} nums
* @param {number} k
* @return {void} Do not return anything, modify nums in-place instead.
*/
var rotate = function(nums, k) {
  var len = nums.length;
  k = k%len;
  var newNums = nums.concat(nums);
  newNums = newNums.slice(len-k,2*len-k);
  for (var i=0;i   nums[i]=newNums[i];
  }
 return nums
};

方法:三次翻转
空间复杂度O(1),时间复杂度O(n)。
移动k次的最终效果其实就是把数组的第k到第n-1之间的数平移到数组的前面,顺序保持不变。
将数组整个翻转就实现了k~n-1的数放到0~k前面的效果,接下来只需要将0~k,k~n-1的顺序恢复过来即可。

var rotate = function(nums, k) {
  const n = nums.length;
  k = k % n;
  if (k === 0) return;
  reverse(nums, 0, n - k);
  reverse(nums, n - k, n);
  reverse(nums, 0, n);
 };

// 翻转数组从begin到end之间的数
var reverse = function(nums, begin, end) {
  let left = begin;
  let right = end - 1;
  while (left < right) {
    let tmp = nums[left];
    nums[left] = nums[right];
    nums[right] = tmp;
    left += 1;
    right -= 1;
  }
};