一网打尽快排

  • 1.初出茅庐
  • 2.小试牛刀
  • 3.炉火纯青(快排)
  • 4.登峰造极(随机快排)

快速排序作为十大经典排序算法之一,在面试场中屡屡出现,不是要求手写快速排序,就是快速排序的变种,为了方便复习,特此总结快速排序

1.初出茅庐

给定一个数组arr,和一个数num,请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。
要求额外空间复杂度O(1),时间复杂度O(N)

  1. 用rightBound记录小于等于num区域的右边界,初始值为-1
  2. 从头遍历数组,如果arr[i] <=num, 那么把arr[i]和小于等于区域的下一个数交换,也就是让arr[i]和下标为rightBound + 1的数交换,然后i++,rightBound++;
  3. 如果arr[i] > num, 则只让i++;

    代码:
public static void test1(int [] arr , int num){int rightBound = -1,i = 0;while (i <arr.length){if(arr[i] <= num) swap(arr,++rightBound,i++);else i++;}}public static void swap(int [] arr, int i, int j){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}

output:

3 5 4 3 5 7 6 8

2.小试牛刀

荷兰国旗问题

给定一个数组arr,和一个数num,请把小于num的数放在数组的 左边,等于num的数放在数组的中间,大于num的数放在数组的 右边。要求额外空间复杂度O(1),时间复杂度O(N)

这题是上一题的加强版

  1. 用rightBound记录小于num区域的右边界,初始值为-1,用leftBound记录大于区域的左边界,初始值为arr.length;
  2. 从头遍历数组,如果arr[i] <num, 那么把arr[i]和小于等于区域的下一个数交换,也就是让arr[i]和下标为rightBound + 1的数交换,然后i++,rightBound++;
  3. 如果arr[i] = num, 则只让i++;
  4. arr[i] > num, 那么把arr[i]和大于区域的下一个数交换,也就是让arr[i]和下标为leftBound - 1的数交换,然后i原地不动,leftBound–;
  5. 当i等于leftBound时循环结束
    (为什么i要原地不动,因为arr[i]和下标为leftBound - 1的数交换后,此时i下标对应的数不知道大小,需要再次比较)

解法的实质是利用双指针把数组中等于num的数往中间挤

代码

  public static void heLanFlag(int [] arr, int num){int rightBound = -1, leftBound = arr.length;int i = 0;while(i < leftBound){if(arr[i] < num) swap(arr,++rightBound,i++);else if(arr[i] == num) i++;else swap(arr,--leftBound,i);}}public static void swap(int [] arr, int i, int j){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}

output:

3 3 4 5 5 7 8 6

3.炉火纯青(快排)

利用荷兰国旗进行分区,分为3个区域(< ,= , >)比分为2个区域(<= 和 >)要快

这种算法最坏情况下复杂度是O(n2)
因为
1,4,3,5,7,6,8,9这种情况,进行快排,每次拿数组最后一个数进行划分,划分后没有右侧大于区域,即都只搞定当前一个数,最坏时间复杂度是O(n2)

代码

 public static void quickSort(int[] arr) {if (arr == null || arr.length < 2) {return;}quickSort(arr, 0, arr.length - 1);}public static void quickSort(int[] arr, int l, int r) {if (l < r) {//int[] p 容量为2,返回的是等于区域的左右边界int[] p = partition(arr, l, r);quickSort(arr, l, p[0] - 1);quickSort(arr, p[1] + 1, r);}}public static int[] partition(int[] arr, int l, int r) {int rightBound = l - 1;int leftBound = r;while (l < leftBound) {if (arr[l] < arr[r]) {swap(arr, ++rightBound, l++);} else if (arr[l] > arr[r]) {swap(arr, --leftBound, l);} else {l++;}}swap(arr, leftBound, r);//返回的是相等值的左,右边界return new int[] { rightBound + 1, leftBound };}public static void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}

4.登峰造极(随机快排)

上面的快速排序由于每次都是拿区域内的最后一个数组按照荷兰国旗的方式进行划分(这里称为分区),因此如果当数据状况是1,4,3,5,7,6,8,9,拿9进行划分,划分区域后只有两个区域,那么时间复杂度会达到O(n2);

因此快速排序改进版是基于随机的思想
从数组中等概率选择一个数与区域的最后一个数进行交换,然后再按照交换后数组的最后一个数进行分区,这样好情况和坏情况就是等概率的!!

因次只需要在前者的基础上随机选择选择一个数即可

public static double random()
返回一个double值为正号,大于等于0.0 ,小于1.0 。返回的值是从该范围(大约)均匀分布而伪随机选择的。

public static void quickSort(int[] arr) {if (arr == null || arr.length < 2) {return;}quickSort(arr, 0, arr.length - 1);}public static void quickSort(int[] arr, int l, int r) {if (l < r) {//Math.random() 返回double大于或等于 0.0并小于 1.0 。swap(arr, l + (int) (Math.random() * (r - l + 1)), r);int[] p = partition(arr, l, r);quickSort(arr, l, p[0] - 1);quickSort(arr, p[1] + 1, r);}}public static int[] partition(int[] arr, int l, int r) {int rightBound = l - 1;int leftBound = r;while (l < leftBound) {if (arr[l] < arr[r]) {swap(arr, ++rightBound, l++);} else if (arr[l] > arr[r]) {swap(arr, --leftBound, l);} else {l++;}}swap(arr, leftBound, r);//返回的是相等值的左,右边界return new int[] { rightBound + 1, leftBound };}public static void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}

根据Master公式并且经过概率累加计算而得(需要数学推导证明)
时间复杂度分析O(N*logN)
空间复杂度分析O(logN)

春招冲刺Day2 [高频算法题] -- 一网打尽快排相关推荐

  1. 春招冲刺Day2 [操作系统] --来聊聊死锁呗?

    死锁 1.死锁的产生 2.处理死锁 2.1预防死锁 2.2 避免死锁 3.死锁检测和死锁解除 3.1JAVA如何检查死锁 面试官:用代码模拟死锁??!!(这里用Synchronized模拟,也可以用R ...

  2. 算法题复习(快排、链表、二分、哈希、双指针)

    目录 1.快速排序复习 2.链表部分复习 203. 移除链表元素 707. 设计链表 206. 反转链表 142.环形链表 II 3.二分法复习 4.哈希法复习 5.双指针复习 **15. 三数之和* ...

  3. 面试必备:高频算法题汇总「图文解析 + 教学视频 + 范例代码」之 字符串处理+动态规划 合集!

    Attention 秋招接近尾声,我总结了 牛客.WanAndroid 上,有关笔试面经的帖子中出现的算法题,结合往年考题写了这一系列文章,所有文章均与 LeetCode 进行核对.测试.欢迎食用 本 ...

  4. 字节跳动2019春招第二次笔试编程题

    字节跳动2019春招第二次笔试编程题 1.变身程序员 题目描述 输入描述 输出描述 示例 示例1 示例2 示例3 分析 参考代码 2.特征提取 题目描述 输入描述 输出描述 示例 示例1 备注 分析 ...

  5. 面试必备:高频算法题汇总「图文解析 + 教学视频 + 范例代码」必问之 排序 + 二叉树 部分!

    排序 所谓排序算法,即通过特定的算法因式将一组或多组数据按照既定模式进行重新排序.这种新序列遵循着一定的规则,体现出一定的规律,因此,经处理后的数据便于筛选和计算,大大提高了计算效率. 对于排序: 我 ...

  6. 面试必备:高频算法题汇总「图文解析 + 教学视频 + 范例代码」必知必会 排序 + 二叉树 部分!

    排序 时光小说网 https://wap.youxs.org/ 所谓排序算法,即通过特定的算法因式将一组或多组数据按照既定模式进行重新排序.这种新序列遵循着一定的规则,体现出一定的规律,因此,经处理后 ...

  7. 面试高频算法题补充系列:木棍切割问题

    前言 了解更多常考高频算法题可以关注 公众号:一个搬砖的胖子 高频算法网站:https://codetop.cc/ 小程序:CodeTop 此题经常在字节跳动后端面试中遇到,尤其是教育部门的三面.我押 ...

  8. 面试高频算法题补充系列:如何判断一个点是否在三角形内?

    前言 了解更多常考高频算法题可以关注 公众号:一个搬砖的胖子 企业面试题库:https://codetop.cc/ 小程序:CodeTop 该题曾出现在字节跳动.腾讯.网易.美团.小马智行等公司的面试 ...

  9. Leetcode高频算法题——字节跳动篇

    众所周知,字节跳动面试非常喜欢考算法题. Leetcode官方的企业题库不仅付费,而且题量非常大. 因此,我从20年7月开始,手动整理牛客面经涉及的Leetcode算法题,并按照频度由高到低进行了排列 ...

最新文章

  1. BZOJ 1923: [Sdoi2010]外星千足虫
  2. 大流行后的数据中心非接触式技术
  3. 剑指offer之判断链表是否包含环
  4. 批量提取文件创建时间_不要眨眼!批量提取文件名,只需30秒
  5. YbtOJ#883-最大的割【带修线性基】
  6. 蓝桥杯 ALGO-5 算法训练 最短路
  7. 行为型设计模式(1)—— 责任链模式(Chain of Responsibility Pattern)
  8. word表格三线表线宽度
  9. daemontools的安装、简介
  10. 华为android界面强刷救砖教程,华为手机救砖教程 华为手机开不了机变砖自救
  11. RabbitMQ安装问题
  12. 基于MATLAB的运动模糊图像处理
  13. 宝塔+青龙面板+机器人+诺兰
  14. 什么是jdk的java运行工具_下面( )是 JDK 中的 JAVA 运行工具。
  15. Latex(Ctex)出现编译错误 ! Misplaced alignment tab character .
  16. css实现渐变图片——曲线救国解决笔记
  17. QST《Linux基础》学习笔记
  18. 郑昀诚出任区块链解决方案公司 Blocknode Communications项目加速组总监
  19. 计算机毕业设计基于Springboot+vue口腔牙科诊所管理系统——计算机毕业设计
  20. 进行股票量化交易接口程序化开发要注意的事项

热门文章

  1. uniapp 生成商品分享通用海报源码详解
  2. 基于Python实现四大名著章节标注汉语拼音
  3. Hibernate之代码创建SessionFactory
  4. c++ mfc BitBlt 绘图
  5. 常用的网络管理命令行
  6. ipad8和ipad air4的区别
  7. 阿里云账号实名认证、域名实名制与网站备案的区别
  8. 支付宝错误 ALIN10146 排查
  9. linux关闭运行程序
  10. abs与fabs的区别和用法