算法——分治(快速排序)

在这里插入图片描述

T04BF

👋专栏: 算法|JAVA|MySQL|C语言

🫵 小比特 大梦想

此篇文章与大家分享分治算法关于快速排序的专题
对于快速排序在我个人主页专栏 <排序> 有详细的介绍,此专题对快排进行了优化操作,并介绍了优化后的快排的几种运用
如果有不足的或者错误的请您指出!

1.颜色分类

题目:颜色分类

1.1解析

这道题目实际上就是将一个给定的只有0,1,2的数组,分成三块,0放在一起,1放在一起,2放在一起

回顾一下移动0问题,实则就是利用双指针将数组划分为两部分.本题也可以利用类似的思想,只不过是将数组划分为3部分

在这里插入图片描述
如图所示,我们标记好left和right,用i来遍历数组,那么这三个变量实际上就将数组划分为4个区间,而我们要做的就是在遍历数组的时候去维护三个区间就好了

(1)arr[i] == 0

为了维护0都在[0,left]这段区间,那么我们要让交换arr[++left]和arr[i],后i++继续遍历

(2)arr[i] == 1

为了维护1都在[left+1,i]这段区间,我们只需让i++即可

(3)arr[i] == 2

为了维护2都在[right,n-1(n为数组长度)],我们要让arr[–right]和arr[i]交换,但是此时i不能++,因为此时从[right,n-1]交换过来的元素还没判断

维护好这三个区间,当i与right相遇即可

class Solution {
    public void sortColors(int[] arr) {
        int left = -1;
        int n = arr.length;
        int right = n;
        for(int i = 0; i < right; ){
            if(arr[i] == 0){
                swap(arr,i++,++left);
            }else if(arr[i] == 1){
                i++;
            }else{
                swap(arr,i,--right);
            }
        }
    }
    public void swap(int[] array,int i,int j){
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
}

2.利用数组划分实现快速排序

题目:数组排序

2.1解析

我们之前学过的快速排序是每次把数组划分为两部分,时间复杂度最好情况下为O(NlogN),但是如果出现大部分的相同元素,就会大大增加时间复杂度

在本题中,我们对之前学过的快速排序进行优化

(1)跟上一题颜色划分一样,在找定基准元素key后,我们把区间每次都分成三部分,

在这里插入图片描述

这样做的好处是,我们再次对不同区间进行递归的时候,就不必再考虑中间 == key 的部分了,因为中间都是相同的值,就没必要参与排序了

而分区域的思想在上一道颜色划分的题目已经讲过

实际上就是用i来遍历区间的时候,分三种情况:(推导过程在上一道题已经演示)

①nums[i] < key => swap(i++,++left)

②nums[i] == key => i++

③nums[i] > key => swap(i,–right)

(2)基准元素

我们在之前讲过的快速排序中,基准元素要么是端点值,要么是利用三数取中,但是最优秀的解法应该是等概率的随机在区间里面找基准元素

那么我们就可以利用随机数的方式,即在区间范围内产生随机数下标 random.nextInt(R-L+1)+L

2.2题解

class Solution {
    public int[] sortArray(int[] nums) {
        qsort(nums,0,nums.length-1);
        return nums;
    }
    private void qsort(int[] nums,int l,int r){
        if(l >= r){
            return;
        }
        Random random = new Random();
        int key = nums[random.nextInt(r-l+1)+l];
        int left = l-1;
        int right = r+1;
        int i = l;
        while(i < right){
            if(nums[i] < key){
                swap(nums,i++,++left);
            }else if(nums[i] == key){
                i++;
            }else{
                swap(nums,i,--right);
            }
        }
        qsort(nums,l,left);
        qsort(nums,right,r);
    }

    private void swap(int[] nums,int i,int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

3.快速选择算法

题目:第k个最大的数

3.1解析

此题实际上是我们快排优化版的运用

在这里插入图片描述

我们在上一题的快速排序中把区间划分为如图所示的三部分,我们分别用a,b,c来表示三部分各自元素个数,那么对于要找的第k个最大元素,就会出现三种情况

(1) c >= k

说明第k个最大元素就是 在c区间的第k个最大元素,那么我们就直接针对c区间进行递归即可,a,b区间不用管

(2)在c >= k 不成立的前提下,如果b + c >= k,那么说明第k个最大元素一定在b区间,而b区间全部都是相同元素,那么直接返回key即可

(2)在前面两个条件都不成立的情况下,那么第k个最大元素只能在a区间,那么我们就要去a区间递归,但是此时就不是找第k个最大元素了

在这里插入图片描述

此时由于大元素都在后面,而我们仅仅只是针对a区间寻找,前k个最大元素有b+c个是在b ,c区间里面的,因此我们要在a中寻找的是第k-b-c大的元素

3.2题解

class Solution {
    public int findKthLargest(int[] nums, int k) {
        return qSort(nums,k,0,nums.length-1);
    }
    private int qSort(int[] nums,int k, int l,int r){
        //此时由于下面已经分类讨论了,因此不可能出现无意义区间的情况
        int key = nums[new Random().nextInt(r-l+1)+l];
        int left = l-1;
        int right = r+1;
        int i = l;
        while(i < right){
            if(nums[i] < key){
                swap(nums,i++,++left);
            }else if(nums[i] == key){
                i++;
            }else{
                swap(nums,i,--right);
            }
        } 
        //三个区间为[l,left] [left+1,right-1] [right,r]
        int b = right - left - 1;
        int c = r - right + 1;
        if(c >= k){
            return qSort(nums,k,right,r);
        }else if(b + c >= k){
            return key;
        }else{
            return qSort(nums,k-b-c,l,left);
        }
    }

    private void swap(int[] nums,int i,int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

4.最小的k个数

题目:最小的k个数

4.1解析

我们一开始想到的方法可能就是直接排序,然后返回前k个最小的数

但是题目对于返回的数组里面的元素是否有序并不关心

在这里插入图片描述

我们在上面的快排中将区间分成三部分,那么对于最小的前k个元素,也会出现三种情况

(1)a > k,那么最小的前k个元素就都在a区间,我们直接去a区间递归即可

(2)在a > k不成立的前提下,如果a + b >= k,那么说明此时最小的前k个元素分成两部分,一部分在a区间,一部分在b区间,由于不关心返回数组里面元素是否有序,那么我们直接返回此时数组的前k个元素即可

(3)在前面两种情况都不满足的前提下,说明此时最小的前k个元素,一部分是a+b的所有元素,一部分是c里面的元素,那么我们就要去c里面递归寻找第k-a-b个元素

4.2题解

class Solution {
    public int[] inventoryManagement(int[] stock, int cnt) {
        qSort(stock,cnt,0,stock.length-1);
        int[] ret = new int[cnt];
        for(int i = 0; i < cnt; i++){
            ret[i] = stock[i];
        }
        return ret;
    }

    private void qSort(int[] stock,int cnt,int l,int r){
        int key = stock[new Random().nextInt(r-l+1)+l];
        int left = l-1;
        int right = r+1;
        int i = l;
        while(i < right){
            if(stock[i] < key){
                swap(stock,i++,++left);
            }else if(stock[i] == key){
                i++;
            }else{
                swap(stock,i,--right);
            }
        }
        //[l,left] [left+1,right-1] [right,r]
        int a = left - l + 1;
        int b = right - left - 1;
        if(a > cnt){
            qSort(stock,cnt,l,left);
        }else if(a + b >= cnt){
            return;
        }else{
            qSort(stock,cnt-a-b,right,r);
        }
    }

    private void swap(int[] nums,int i,int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

感谢您的访问!!期待您的关注!!!

在这里插入图片描述

T04BF

🫵 小比特 大梦想

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数组方法汇总

数组和链表类似&#xff0c;都是用双指针&#xff0c;但数组不需要额外的指针&#xff0c;可以使用索引来当作指针。&#xff08;链表的时候要注意&#xff0c;什么时候是移动的指针&#xff0c;什么时候是改变的节点&#xff09;删除有序数组中的重复项 注意&#xff0c;本题中…

【数据结构】--- 探索栈和队列的奥秘

关注小庄 顿顿解馋૮(˶ᵔ ᵕ ᵔ˶)ა &#x1f4a1;个人主页&#xff1a;9ilk &#x1f4a1;专栏&#xff1a;数据结构之旅 上回我们学习了顺序表和链表&#xff0c;今天博主来讲解两个新的数据结构 — 栈和队列 &#xff0c; 请放心食用 文章目录 &#x1f3e0; 栈&#x1…

红黑树内部结点数量分析

红黑树内部结点数量分析 一、红黑树的性质二、黑高与内部结点数量2.1最大内部结点数量2.2最小内部结点数量 三、伪代码实现四、C语言代码实现五、结论 红黑树是一种自平衡的二叉搜索树&#xff0c;它通过一系列复杂的性质和操作来维持平衡&#xff0c;从而确保各种动态集合操作…

来get属于你的达坦科技令人心动的offer吧!

我们是谁 达坦科技始终致力于打造高性能Al Cloud 基础设施平台DatenLord&#xff0c;积极推动AI应用的落地。DatenLord通过软硬件深度融合的方式&#xff0c;提供高性能存储和高性能网络。为AI 应用提供弹性、便利、经济的基础设施服务&#xff0c;以此满足不同行业客户对AICl…

【Unity每日一记】如何让Sprite精灵图集的背景图层变成透明,方便切割

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…

CSS基础:4种简单选择器的详解

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。大专生&#xff0c;2年时间从1800到月入过万&#xff0c;工作5年买房。 分享成长心得。 261篇原创内容-公众号 后台回复“前端工具”可获取开发工具&#xff0c;持续更新中 后台回复“前端基础…

Axure案例分享—垂直手风琴(附下载地址)

今天分享的案例是Axure8(兼容9和10)制作的垂直手风琴 一、功能介绍 折叠或展开多个面板内容&#xff0c;默认为展开一项内容&#xff0c;点击任一收起的选项&#xff0c;展开面板&#xff0c;其他面板收起二、制作过程 原型是由矩形组件以及动态面板构成&#xff0c; 拖入一…

面向C++程序员的Rust教程(二)

先序文章请看&#xff1a; 面向C程序员的Rust教程&#xff08;一&#xff09; 所有权与移动语义 要说Rust语言跟其他语言最大的区别&#xff0c;那笔者觉得非数这个所有权和移动语义莫属。 深浅复制 对于绝大多数语言来说&#xff0c;变量/对象之间的赋值通常都是复制语义。…

python标准数据类型--元组常用方法

在Python中&#xff0c;元组&#xff08;Tuple&#xff09;是一种不可变的有序集合&#xff0c;它与列表类似&#xff0c;但是元组中的元素不能被修改。元组通常用于存储不可变的数据集合&#xff0c;例如一组常量或者一组固定的值。本篇博客将介绍一些Python中元组的常用方法&…

软考高级架构师:人工智能芯片概念和例题

一、AI 讲解 人工智能芯片是专门设计来处理与人工智能&#xff08;AI&#xff09;相关的任务的集成电路。这些芯片针对AI应用的高计算需求进行了优化&#xff0c;以提升处理速度和效率&#xff0c;同时降低能耗。它们在AI领域&#xff0c;如深度学习、机器学习和数据分析中发挥…

python爬虫获取豆瓣前top250的标题(简单)

今天是简略的一篇&#xff0c;简单小实验 import requests from bs4 import BeautifulSoup# 模拟浏览器的构成&#xff08;请求头&#xff09; headers {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Ch…

10 款最佳 Mac 数据恢复软件,在为时已晚之前值得尝试

查看 10 年适用于 Mac 的 2024 款最佳免费数据恢复软件&#xff0c;可在大多数在线搜索中找到。精选列表将帮助您做出明智的决定并节省您的时间和精力。 10 款最佳 Mac 数据恢复软件 很明显&#xff0c;您此后将面临数据丢失事件。理所当然地&#xff0c;您期待一款可靠、与您…

中文大模型隐私保护哪家强?InternLM 与 Baichuan2 胜出!

引言&#xff1a;中文大模型隐私保护能力探索 本文研究了大语言模型&#xff08;LLMs&#xff09;对隐私和安全的影响&#xff0c;采用了三层渐进框架对语言系统的隐私进行评估。主要目标是全面评估LLMs对私人信息的敏感性&#xff0c;并检查其在识别、管理和保护敏感数据方面…

微信小程序短链接工具推荐

现在微信小程序大行其道&#xff0c;但工作中大部分人选择了短链接的方式来推广微信小程序&#xff0c;那么微信小程序短链接工具哪个好?今天就分享一篇从网上看到的关于《微信小程序短链接工具推荐》文&#xff0c;作者是souki&#xff0c;一起来看看吧! 一、缩链 1、生成方…

【智能算法】阿基米德优化算法(AOA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2020年&#xff0c;Hashim等人受到阿基米德定律启发&#xff0c;提出了阿基米德优化算法&#xff08;Archimedes Optimization Algorithm&#xff0c;AOA&#xff09;。 2.算法原理 2.1算法思想 …

python导入本地当前目录下的文件和父目录下的文件

今天我想要导入本地当前目录下的文件和父目录下的文件&#xff0c;网上查了很多教程&#xff0c;但还都是报错&#xff0c;最后几经尝试&#xff0c;终于成功解决了这一问题&#xff0c;在这里详细记录一下过程&#xff0c;同时也希望能够对大家有所帮助~~~:&#xff09; 导入…

Python人工智能应用---中文分词词频统计

目录 1.中文分词 2.循环分别处理列表 &#xff08;1&#xff09;分析 &#xff08;2&#xff09;代码解决 3.词袋模型的构建 &#xff08;1&#xff09;分析需求 &#xff08;2&#xff09;处理分析 1.先实现字符串的连接 2.字符串放到新的列表里面 4.提取高频词语 &…

vivado 向 SVF 目标添加器件

向 SVF 目标添加器件 创建 SVF 目标后 &#xff0c; 可向其中添加器件以定义 SVF JTAG 器件链配置。 SVF JTAG 器件链配置应与目标硬件链相匹配 &#xff0c; 以 确保能正确执行 SVF 文件。 使用 Vivado IDE 单击“ ”按钮以向 SVF 链添加赛灵思器件或非赛灵思器件。…

程序·人生

诡异之极 2024.03.12 清新环境&#xff08;股票代码002573&#xff09;委托卖出 20000股&#xff0c;委托价4.58&#xff0c;当日最高价4.57 2024.03.11 清新环境&#xff08;股票代码002573&#xff09;委托卖出 20000股&#xff0c;委托价4.55&#xff0c;当日最高价4.54 …

【Python系列】读取 Excel 第一列数据并赋值到指定列

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…