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

news2025/1/22 23:35:30

文章目录

    • 算法介绍 :
    • 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.coloradmin.cn/o/1789544.html

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

相关文章

15 - 有趣的电影(高频 SQL 50 题基础版)

15 - 有趣的电影 select* from cinema wheredescription!boring and id%2!0 order by rating desc;

黑龙江等保测评有哪些内容?

与等保1.0相比&#xff0c;新的等保2.0版本有了很大的变化&#xff0c;评估的内容、评估的标准也有了很大的差异。那么新版的《等保2.0》实施后&#xff0c;我们要测试什么&#xff1f; 等保测评首先是有十个大项&#xff0c;安全物理环境&#xff0c;安全区域边界&#xff0c;…

标准发布 | 反渗透和纳滤水处理膜修复再利用技术指南

一、编制单位 本文件由浙江大学、中华环保联合会水环境治理专业委员会提出。 本文件由中华环保联合会归口。 本文件主编单位&#xff1a;浙江大学、河南一膜环保技术有限公司、安徽精高水处理有限公司、国能龙源环保有限公司、湖南沁森高科新材料有限公司。 本文件参编单位&…

getway整合sentinel流控降级

3. 启动sentinel控制台增加流控规则&#xff1a; 根据API分组进行流控&#xff1a; 1.设置API分组&#xff1a; 2.根据API分组进行流控&#xff1a; 自定义统一异常处理&#xff1a; nginx负载配置&#xff1a;

Redis位图

简介 在我们平时开发过程中&#xff0c;会有一些bool型数据需要存取&#xff0c;比如用户一年的签到记录&#xff0c;签了是1&#xff0c;没签是0&#xff0c;要记录365天。如果使用普通的key/value&#xff0c;每个用户要记录365个&#xff0c;当用户上亿的时候&#xff0c;需…

湖南(选址调研)源点咨询 商铺开业前选址调研重要性与流程解析

湖南长沙&#xff08;市场定位&#xff09;源点市场调研认为&#xff0c;选址前首要的准备工作就是对店铺地址进行周密的调查&#xff0c;列出一份详尽的选址调查报告&#xff0c;从而逐一分析店铺的选址的利与弊&#xff0c;最后确定该地址是否适合店铺的运营。源点调研通过多…

电商API商品数据采集接口||助力电商企业采集商品大数据提高开发效率

提高开发效率&#xff1a;电商API接口允许不同的应用程序之间高效地进行交互&#xff0c;节省了大量的人力物力成本&#xff0c;使得开发者可以将更多时间和精力集中于自身的核心业务。 增加数据安全性&#xff1a;通过对数据进行安全加密&#xff0c;API接口实现了对数据的保护…

硬件26、EDA绘制板框

1、放置-板框-矩形 2、在pcb上绘制出需要大小的板框 3、设置板框四个角为圆弧状&#xff0c;在右侧属性栏设置圆角半径

系统工程与信息系统基础

三、企业信息化 目的&#xff1a;提高企业的竞争力 信息化需求&#xff1a; 战略需求&#xff1a;提升组织的竞争能力 运作需求&#xff1a;实现信息化战略目标、运作策略、人才培养的需要 技术需求&#xff1a;信息技术层面上对系统的完善、升级、集成 企业信息化方法&…

ArcGIS for Vue3

二维&#xff1a; 1、创建vue项目 npm create vitelatest 2、安装ArcGIS JS API依赖包 npm install arcgis/core 3、引入ArcGIS API for JavaScript模块 <script setup> import "arcgis/core/assets/esri/themes/light/main.css"; import Map from arcgis…

功效系数法

功效系数法&#xff08;Efficacy Coefficient Method&#xff09;是一种综合评价方法&#xff0c;它根据多目标规划的原理&#xff0c;对每个评价指标确定一个满意值和不允许值&#xff0c;以满意值为上限&#xff0c;以不允许值为下限。计算各指标实现满意值的程度&#xff0c…

Gorm中time.time的默认时区

问题复现 期望查询结果时区使用本机的默认时区&#xff08;东八区&#xff09;&#xff1a; 2024-06-05 04:43:54 0800 CST 实际查询结果&#xff08;UTC&#xff09;&#xff1a; 2024-06-04 20:43:54 0000 UTC 如何解决 问题是通过gorm查询mysql数据库时做了转化&#xff0…

目标检测数据集 - 城市道路行驶车辆检测数据集下载「包含VOC、COCO、YOLO三种格式」

​​​数据集介绍&#xff1a;城市道路行驶车辆检测数据集&#xff0c;真实监控场景高质量图片数据&#xff0c;涉及场景丰富&#xff0c;比如城市道路快速行驶车辆、城市道路慢速行驶车辆、城市道路密集行驶车辆、城市道路夜间低光行驶车辆数据等。数据集标注标签划分为 "…

信息可溯、安全可控 | SW-LIMS 采测分离监测模式解析

数据的准确性在环境监测过程中至关重要,为了确保环监数据的真实有效,并满足“全程留痕、全程监控、信息可溯、安全可控”的要求,采测分离监测模式是一个有效的解决方案。 这种模式通过将样品采集和样品检测交由不同的单位完成,形成了相互独立、相互监督的工作机制,有助于减少潜…

七.传输层协议——再谈UDP协议

一.传输层协议地位 在上一节中&#xff0c;我们提到到了HTTP,HTTPS等应用层协议&#xff0c;现在我们就要进一步向下挖掘&#xff0c;来到我们的传输层协议 假如说应用层负责传递的是数据的内容&#xff0c;专注于为⽤户提供应⽤功能&#xff1b;那传输层协议负责的就是传输的…

EXCEL从图片链接获取图片

step1: 选中图片地址列 step2:开发工具→Visual Basic 文件→导入 导入我制作的脚本&#xff08;代码见文章末尾&#xff09; 点击excel的小图标回到表格界面。 点击【宏】 选中刚才导入的脚本&#xff0c;点执行&#xff0c;等待完成。 代码本体&#xff1a; Sub InsertPict…

最大堆,最小堆,优先队列,堆排序 LC例题-找第K大元素

LC215 数组中的第K个最大元素 class Solution {static Comparator<Integer> cmp new Comparator<Integer>(){Overridepublic int compare(Integer i1, Integer i2){return i1 - i2;//升序排列// return i2 - i1&#xff1b;//降序}}; public static int findKthL…

Linux中,ll 命令 列出目录的内容

文章目录 1、2、3、4、5、 1、 在Linux中&#xff0c;ll 通常是一个别名&#xff08;alias&#xff09;用于 ls -l 命令。ls 命令用于列出目录的内容&#xff0c;而 -l 选项会以长格式&#xff08;long format&#xff09;显示信息&#xff0c;包括文件或目录的权限、所有者、…

android 开机动画执行流程

android深入了解开机动画 开机动画的种类 1&#xff1a;View绘制 2&#xff1a;逐帧动画&#xff1a;比较主流的方式&#xff0c;一般动画的文件打包成 bootanimation.zip 存储到 /system/media/ 下。一般.zip文件 > 5M 就会有明显的卡顿&#xff0c;所以一般开机动画只有…

[next.js]pwa缓存

配置Next.js (v14 App Router模式) 使其支持PWA缓存&#xff0c;配置server worker和mainfest.json&#xff0c;让项目支持离线访问和可安装。 安装依赖next-pwa npm i next-pwa配置next.config.js const path require(path);const withPWAInit require(next-pwa);// 判断…