算法-随机快排及荷兰国旗优化

文章目录

    • 算法介绍 :
    • 1. 随机快排解析
    • 2. 荷兰国旗问题
    • 3. 随机快排优化
    • 4. 总结随机快排

算法介绍 :

随机快速排序和传统的快速排序的逻辑本质是一致的,都是找到一个值作为划分的中间位置,左边数值均小于该数值,右边数值均大于该数值,但是与传统的快排又不一致的是,我们的这个位置是通过随机获得的,对于随机行为的时间复杂度不能简单的按照最坏的情况解读

1. 随机快排解析

下面是我们随机快排的代码实现

public class Sort {public static void quickSort(int[] nums) {if (nums == null || nums.length <= 1) {return;}quickSort(nums, 0, nums.length - 1);}//下面是经典版本随机快排的函数主体private static void quickSort(int[] nums, int left, int right) {if (left >= right) {return;}//在left -- right范围上随机出来一个数字int randn = nums[left + (int) (Math.random() * (right - left + 1))];int boundary = partiton(nums, left, right, randn);quickSort(nums, left, boundary - 1);quickSort(nums, boundary + 1, right);}//经典快排的partition过程private static int partiton(int[] nums, int left, int right, int randn) {//逐个遍历的下标int i = left;//用来区别 <= randn的边界位置(已经越界了)int j = left;//记录找到的x的位置(用于交换)int randIndex = left;while (i <= right) {if (nums[i] <= randn) {swap(nums, i, j);if (nums[j] == randn) {randIndex = j;}i++;j++;} else {i++;}}swap(nums, j - 1, randIndex);return j - 1;}private static void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}

下面主要解析一下上述代码的逻辑是什么
首先我们通过
(int)(Math.random()*(right - left + 1)) + left
这段代码可以随机产生一个left – right的下标值
然后我们就拿到该位置的随机数作为划分
之后通过partiton过程来进行快排的逻辑,其中定义了两个指针,一个遍历数组下标,一个进行边界位置的扩大,当遍历到随机数的时候我们就记录下来该随机数的下标,然后通过左右区间调用递归过程完成排序, 但是这个快排的逻辑在leetcode上是跑不过全部的,因为你一轮只能排出来一个数据

2. 荷兰国旗问题

在这里插入图片描述
荷兰国旗问题可以为我们的接下来的排序优化打下基础, 上面的排序说了我们创造了一个左边界线, 那为什么不创建一个有边界线呢 ? 荷兰国旗就是这样解决的,但是要注意的是,在移动右边界线的时候,遍历的下标值不可以移动,在移动左边界线却可以, 因为左边已经遍历过一轮了, 可以确定交换过来的元素属性,但是右边是不确定的, 代码实现如下

class Solution {public void sortColors(int[] nums) {int first = 0;int last = nums.length - 1;int i = 0;while(i <= last){if(nums[i] == 0){swap(nums,i++,first++);}else if(nums[i] == 1){i++;}else{swap(nums,i,last--);}}}public void swap(int[] nums,int i,int j){int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}

3. 随机快排优化

有了上面的荷兰国旗的基础,我们的快排优化也是这样做的,逻辑也是定出来两个边界,然后逐个进行移动…
代码实现如下

/*** 下面是根据荷兰国旗问题的改进版本(分为三个区间, 一次搞定一批)* 下面这个两个属性是左右边界的越界位置*/
public class Sort{public int first = 0;public int last = 0;public void quickSortImprove(int[] nums) {if (nums == null || nums.length <= 1) {return;}quickSortImprove(nums, 0, nums.length - 1);}public void quickSortImprove(int[] nums,int left,int right){if (left >= right) {return;}int randn = nums[left + (int) (Math.random() * (right - left + 1))];partitonImprove(nums,left,right,randn);int fir = first;int la = last;quickSortImprove(nums,left,fir - 1);quickSortImprove(nums,la + 1, right);}private void partitonImprove(int[] nums,int left,int right,int randn){first = left;last = right;int i = left;while(i <= last){if(nums[i] < randn){swap(nums,i++,first++);}else if(nums[i] == randn){i++;}else{swap(nums,i,last--);}}}private static void swap(int[] nums, int i, int j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}

在这里插入图片描述

4. 总结随机快排

随机快速排序算法

  • 随机快速排序的经典版本就是下面这样,随机出一个位置作为分界点,然后左右递归…
  • 我们下面的快排代码里面的 j 是作为左/右边界的越界位置存在 --> 随着下标指针的遍历(边界在不断地扩大)
  • Math.random方法的常数时间复杂度属于随机行为的时间复杂度
  • 荷兰国旗问题其实是随机快速排序的一种优化方式
  • 因为原本我们随即快排一次只能搞定一个数字, 优化之后我们一次可以搞定一批 x == randNum 的数据
  • 随机快速排序的时间复杂度与空间复杂度的估计
  • 关于随机行为的时间复杂度的估计不可以采用最坏的情况估计(因为最坏的情况就是无穷大),应该采用期望的方式估计
  • 最好情况(正好是中点位置) --> 时间复杂度 O(N*LogN)(Master公式) 空间复杂度O(LogN)(堆栈中树的高度)
  • 最坏情况(边界位置) --> 时间复杂度 O(N^2) 空间复杂度O(N)(堆栈中树的高度)
  • 经过大批数学家的证明(因为最终的时间复杂度应该算的是期望值(包含随机行为作为核心步骤))
  • –> 结论就是 时间复杂度 O(N*LogN) 空间复杂度O(LogN) --> 详见算法导论(有详细证明)
  • 所以 : 随机快排要比普通的快排更加优秀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/20288.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

国内的期权模拟账户怎么申请?

国内的期权模拟账户可以在券商和期权分仓平台处申请开通&#xff0c;期权相比于股票具有杠杆投资、风险控制等新特性。 期权模拟交易客户端能够提供期权的开平仓交易、备兑开仓&#xff0f;平仓、行权等交易指令&#xff0c;下文为大家介绍国内的期权模拟账户怎么申请&#xff…

2024 cicsn Ezheap

文章目录 检查 libc2.35利用adddeleeditshow 思路exp结果 检查 libc2.35 利用 add 0x80个chunk&#xff0c;遍历选一个没有被用的&#xff0c;输入的size<0x501,然后malloc后会清零安装输入的size&#xff0c;然后输入内容&#xff0c;长度也是输入的size dele 指定索引…

【科普】生活中常见的不同后缀的应用和软件

生活中常见的安装包后缀&#xff0c;它们通常与特定的操作系统或平台关联。这里是一些常见后缀的详细说明&#xff1a; .exe - 这是Windows操作系统的可执行文件。它通常用于安装程序或运行软件。只要双击.exe文件&#xff0c;安装向导就会引导你完成安装过程。 .apk - 这是An…

LeetCode 164. LRU 缓存

LRU缓存 题目描述示例解题思路C 代码 题目描述 请你设计并实现一个满足 LRU (最近最久未使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量capacity初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#x…

第十六课,海龟画图:设置画笔颜色、宽度函数,移动画笔函数

一&#xff0c;turtle.color()&#xff1a;画笔颜色函数 这个函数能设置画笔画出来的颜色&#xff0c;当然&#xff0c;使用它之前你需要认识有哪些“颜料”可供你选择&#xff0c;turtle库的color()函数可以选择以下颜色&#xff1a; "white" 白色&#xff08;建议…

3步轻松月入过万,APP广告新模式大揭秘!

万万没想到&#xff1a;用这个APP广告模式&#xff0c;月入过万竟然如此简单&#xff01; 在移动应用开发的世界里&#xff0c;变现一直是一道难题。 许多APP开发者和产品经理为了提高收益、增强用户黏性&#xff0c;不断尝试各种策略。 然而&#xff0c;很多时候&#xff0c…

2024-6-1 石群电路-20

2024-6-1&#xff0c;星期六&#xff0c;18:24&#xff0c;天气&#xff1a;晴&#xff0c;心情&#xff1a;晴。已经到学校啦&#xff0c;本来打算今天休息一天不更了&#xff0c;但是觉得可以更新完再休息&#xff0c;没有这么累&#xff0c;哈哈哈哈&#xff0c;这就不得不说…

阿里云部署nodejs

目录 1、安装node.js 1-1 进入opt/software 1-2 下载node.js安装包 1-3 解压 2 配置环境变量 2-1 vim中配置环境变量 2-2 命令行中保存环境变量 2-3 检查安装版本 2-3 更换镜像 3、上传node.js项目 1-1 启动项目 1-2 配置对应的安全组 ​编辑 4、pm2启动多个node项…

Linux目录的基本结构(RHEL8系统基本使用之文件操作)

1.Linux的目录树结构 2.各目录的功能介绍 3.理解文件路径表示方法 Who&#xff1f;——>当前登录的用户 Where?——>路径 我要在哪儿创建文件&#xff1f; 我要删除什么地方的什么文件&#xff1f; 我所要查看的文件在哪里&#xff1f; What?——>操作命令 Ho…

Ultralytics x SwanLab:可视化YOLO模型训练

Ultralytics是YOLO官方团队推出的CV训练与推理框架&#xff0c;不仅支持目标检测任务&#xff0c;还支持分割、姿态识别、分类等更多任务。 SwanLab是一个深度学习实验管理与训练可视化工具&#xff0c;由西安电子科技大学团队打造&#xff0c;融合了Weights & Biases与Ten…

java web爬虫

目录 读取本地文件 从网站读取文件 java爬虫 总结 读取本地文件 import java.io.File; import java.io.PrintWriter; import java.util.Scanner;public class ReplaceText {public static void main() throws Exception{File file new File("basic\\test.txt"…

vue3:插槽、具名插槽、条件插槽、作用域插槽、具名作用域插槽 一次性搞清楚 --- 通俗易懂

1、插槽的使用&#xff1a; ~父组件index.vue&#xff1a; <h3>我是父组件testSlot</h3> <!-- 调用子组件alertBox测试插槽 --> <alertBox></alertBox> <alertBox>Something good will be happened. /alertBox> <br> ~alertBo…

钓虾馆计时计费怎么用,佳易王钓虾馆钓鱼场计时器工具软件操作教程

钓虾馆计时计费怎么用&#xff0c;佳易王钓虾馆钓鱼场计时器工具软件操作教程 一、前言 以下软件操作教程以&#xff0c;佳易王钓虾馆钓鱼场计时计费软件为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 可以多种单价计费方式&#xff0c;在系统…

Elasticsearch 认证模拟题 - 4

一、题目 生成快照&#xff0c;或快照生命周期 1.1 考点 快照生命周期&#xff08;最好通过界面化配置&#xff09;创建仓库创建快照 &#xff08;因为这个需要部署共享文件&#xff0c;所以这个我就在虚拟机上简单操作一下&#xff09; 注&#xff1a; 部署共享文件系统可…

【开发利器】使用OpenCV算子工作流高效开发

学习《人工智能应用软件开发》&#xff0c;学会所有OpenCV技能就这么简单&#xff01; 做真正的OpenCV开发者&#xff0c;从入门到入职&#xff0c;一步到位&#xff01; OpenCV实验大师Python SDK 基于OpenCV实验大师v1.02版本提供的Python SDK 实现工作流导出与第三方应用集…

MySql全文索引+Ngram

一、关于Ngram 1.1 什么是ngram MySQL 内置的全文解析器使用单词之间的空格作为分隔符&#xff0c;这对于不使用空格做分隔符的语言是一种限制。为了解决这一限制&#xff0c;MySQL提供了一个支持中文、日文和韩文&#xff08;CJK&#xff09;的ngram全文解析器。ngram 全文解…

Python | R 雌雄配对和鱼仔变异马尔可夫链

&#x1f3af;要点 &#x1f3af;马尔可夫链&#xff1a;&#x1f58a;天气状态马尔可夫链和马尔科夫矩阵 | &#x1f58a;多项式隐马尔可夫模型&#xff0c;及其高斯分布 | &#x1f58a;算法&#xff1a;前向、后向、前向-后向、维特比算法 | &#x1f58a;最大似然学习、特…

图像加雾算法的研究与应用

目录 前言 一、图像加雾 1、基于传统方法的雾图合成 2、基于深度学习的雾图合成 3、基于Lightroom Classic实现软件加雾 4、基于深度图的方法实现加雾 二、开源的数据集 三、参考文章 前言 在去雾任务当中&#xff0c;训练和评估去雾算法需要大量的带有雾霾和无雾霾的…

聊聊几种常见的分布式Session解决方案

highlight: xcode theme: vuepress 问题引入&#xff1a;什么是分布式Session&#xff1f; 分布式 Session 是指在多台服务器之间共享和管理用户的会话数据&#xff0c;使得用户的会话状态能够在不同的服务器上保持一致。这样&#xff0c;无论用户的请求被路由到哪台服务器&…

常见的几种编码方式

常见的编码方式及其特点&#xff1a; 编码方式的设计是为了适应不同的字符集和应用需求&#xff0c;因此它们在表示字符时使用的位数和字节数各不相同 常见编码方式及其位数和字节数 ASCII&#xff08;American Standard Code for Information Interchange&#xff09;&#x…