#快速排序

Quick Sort

也叫分区交换排序

快速排序使用分治法(Divide and conquer)策略

根据一个基准(例如第一个数)把一个数组分为较小和较大的 2 个子数组这就是分区

分区的时候将数字交换过去,这就是交换

#简版

function sortArray(nums: number[]): number[] {
  if (nums.length <= 1) {
    return nums
  }

  // 最后一个数为基准
  const pivot = nums[nums.length - 1]
  const less = []
  const greater = []

  // 分为比基准大和比基准小两个数组
  for (let i = 0; i < nums.length - 1; i++) {
    if (nums[i] < pivot) {
      less.push(nums[i])
    } else {
      greater.push(nums[i])
    }
  }

  // 递归
  return [...sortArray(less), pivot, ...sortArray(greater)]
}

#步骤

  1. 将最后一个数作为基准
  2. 从第一个数开始到倒数第二个数,将小于基准的数依次交换到左边,最后将最后一个数交换到左边的最后
  3. 对左右数组递归做同样处理

#代码实现

function sortArray(nums: number[]): number[] {
  if (nums.length <= 1) {
    return nums
  }

  quickSort(nums, 0, nums.length - 1)

  return nums
}

function quickSort(nums: number[], left: number, right: number) {
  if (left < right) {
    // 分区并返回基准下标
    const pivotIndex = partition(nums, left, right)
    console.log(nums)
    // 递归排序左边
    quickSort(nums, left, pivotIndex - 1)
    // 递归排序右边
    quickSort(nums, pivotIndex + 1, right)
  }

  return nums
}

function partition(nums: number[], left: number, right: number) {
  // 假设基准值在最右
  const pivot = nums[right]
  // 左边更小数组的尾下标(初始基准下标)
  let i = left

  // 注意最右边基准值单独处理
  for (let j = left; j < right; j++) {
    // 如果数小于等于基准值,交换到左边数组
    if (nums[j] < pivot) {
      ;[nums[i], nums[j]] = [nums[j], nums[i]]
      i++
    }
  }

  // 交换最右边基准值到左边数组尾部(基准下标位置)
  ;[nums[i], nums[right]] = [nums[right], nums[i]]

  return i
}

#性能

时间复杂度:O(n²) 空间复杂度:O(logn) 稳定性:不稳定