【问题标题】:Better/faster algorithm to rotate an array?更好/更快的算法来旋转数组?
【发布时间】:2020-03-08 21:15:54
【问题描述】:

给定一个数组,将数组向右旋转 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]

我的解决方案:

var rotate = function(nums, k) {
while(k>0){ 
 let lastelm = nums[nums.length-1];
  for(let i =nums.length; i>0;i--){
    temp = nums[i-1];
    nums[i-1] = nums[i-2];    
  }
  nums[0]=lastelm
  k--;
 }     
};

我认为我的解决方案是 O(k*nums.length)

我修改整个数组的次数是 k

有什么更好的方法来解决这个问题?

【问题讨论】:

  • 我认为这属于codereview.stackexchange.com
  • @mplungjan 我不同意。性能在代码中总是很重要,唯一的问题是程度。这个问题清楚地提到了大 O 表示法中某事物的速度有多快,这是一个纯粹的客观衡量标准。

标签: javascript arrays algorithm data-structures


【解决方案1】:

您可以使用.slice 从数组中取出两个切片 - 一个从开头开始,在中间结束,另一个切片从中间开始,在结尾结束。然后以相反的顺序重新组合它们:

const rotate = (nums, k) => [...nums.slice(-k), ...nums.slice(0, -k)];
console.log(rotate([1,2,3,4,5,6,7], 1));
console.log(rotate([1,2,3,4,5,6,7], 3));

如果你改变现有的数组,那么:

const rotate = (nums, k) => {
  const moveAfter = new Array(k).concat(nums.slice(0, -k));
  Object.assign(nums, nums.slice(-k), moveAfter);
  return nums;
};
console.log(rotate([1,2,3,4,5,6,7], 1));
console.log(rotate([1,2,3,4,5,6,7], 3));

如果k 可能大于数组的长度,请先对其取模:

const rotate = (nums, kPossiblyOutOfRange) => {
  const k = kPossiblyOutOfRange % nums.length;
  return [...nums.slice(-k), ...nums.slice(0, -k)];
}
console.log(rotate([1,2,3,4,5,6,7], 1));
console.log(rotate([1,2,3,4,5,6,7], 8));
console.log(rotate([1,2,3,4,5,6,7], 3));

【讨论】:

  • 有趣,但似乎有问题(除非我遗漏了什么):rotate([1,2,3,4,5,6,7], 1) -> [3, 4 , 5, 6, 7, 1, 2] 旋转([1,2,3,4,5,6,7], 0) -> [2, 3, 4, 5, 6, 7, 1]跨度>
  • 哦,我在向左旋转,必须传递一个负索引来代替
  • 我想强调的另一个发现:1)这不会编辑原始数组,而是返回新数组; 2) 不适用于 k > 7
  • @CertainPerformance 我认为您在代码中的某处需要k = k % nums.length; 之类的东西
【解决方案2】:

最简单的方法是在读取或写入数组时跟踪移位。 IE。存储一个常量“shift”,当您从索引 i 处的数组读取或写入时,调整为 (i + shift) %(数组大小)。

【讨论】:

  • 这是常数时间,或 O(1)
【解决方案3】:

unshiftpop 结合起来似乎可以解决问题:

var rotate = function(nums, k) {
    while (k > 0) { 
        nums.unshift(nums.pop());
        k--;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-13
    • 2020-08-12
    • 2021-04-29
    • 2012-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多