算法:将一个数组旋转K步

25 阅读1分钟

题目

image.png

思路

image.png

代码

/*
*  使用pop和unshift O(n^2)
*/
function rotate1(arr: number[], k: number): number[] {
  const length = arr.length
  if (!k || length === 0) return arr
  const step = Math.abs(k % length) // abs 取绝对值
  // O(n^2)
  for (let i = 0; i < step; i++) { // O(n)
    const n = arr.pop()
    if (n!=null) {
      arr.unshift(n) // 数组是一个有序结构 unshift操作非常慢(shift splice 等 也一样)O(n)
    }
  }
  return arr
}
// 使用concat O(1)
function rotate2(arr: number[], k: number): number[]{
  const length = arr.length
  if (!k || length === 0) return arr
  const step = Math.abs(k % length) // abs 取绝对值

  const part1 = arr.slice(-step); // slice 不会动原数组 所以比较快
  const part2 = arr.slice(0, length - step);
  const part3 = part1.concat(part2)
  return part3
}

// 功能测试
const arr = [1, 2, 3, 4, 5, 6, 7]
const arr1 = rotate1(arr, 3)
const arr2 = rotate2(arr, 3)
// console.log(arr.slice(1))
console.info(arr1)
console.info(arr2)

// 性能测试
const arr3:number[] = []
for (let i = 0; i < 10 * 10000; i++){
  arr3.push(i)
}
console.time('rotate1')
rotate1(arr3, 9 * 10000)
console.timeEnd('rotate1') // 885ms O(n^2)

// 性能测试
const arr4:number[] = []
for (let i = 0; i < 10 * 10000; i++){
  arr4.push(i)
}
console.time('rotate2')
rotate2(arr4, 9 * 10000)
console.timeEnd('rotate2') //1ms O(1)


复杂度分析

image.png

答案

function rotate(arr: number[], k: number): number[]{
  const length = arr.length
  if (!k || length === 0) return arr
  const step = Math.abs(k % length) 
  const part1 = arr.slice(-step); 
  const part2 = arr.slice(0, length - step);
  const part3 = part1.concat(part2)
  return part3
}

image.png

重点:

image.png