【数据结构与算法】快排的写法

127 阅读1分钟

快速排序

快排是一种平均O(nlogn)时间复杂度的排序算法,最坏时间复杂度为O(n^2)。

基本思想

  1. 找一个分界点x(第一个数、中点、随机)
  2. 将数组分为两个部分,使得左边<=x,右边>=x
  3. 对左右部分递归进行下去,直到长度为1直接返回

划分区间的方法

  • 借用额外数组(不推荐,有额外空间浪费)
    • 遍历原数组,小于等于界限的的放左边,大于等于的放右边
  • 双指针原地修改
    • l,r指向数组的右两端,符合条件就不断向中间移动,两个都不符合就交换一下,继续判断

代码示例

func quickSort(q []int, l int, r int) {
   if l < r {
      // 双指针划分
      mid, i, j := q[(l+r)/2], l-1, r+1
      for i < j {
         i++
         for q[i] < mid {
            i++
         }
         j--
         for q[j] > mid {
            j--
         }
         if i < j {
            q[i], q[j] = q[j], q[i]
         }
      }
      // 对左右部分递归
      quickSort(q, l, j)
      quickSort(q, j+1, r)
   }
}

快排的非递归写法

可以使用一个队列,存储要递归计算的lr边界,这里使用bfs遍历。 当然也可以使用栈,就是dfs遍历,结果都一样。

快排的链表写法

链表操作的思路和数组差不多,分成三个部分:小于x,等于x大于x。然后将这三个部分拼接在一起即可

快排解决TopK问题

经常遇到一些题目让我们求第k大、第k小、前k大、前k小(不要求顺序)的场景。又要求时间复杂度为O(n),那么可以对快排进行化简:

  • 只递归对我们有用的部分,答案不在的部分就无需递归下去了