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

news2024/10/10 8:27:00

在这里插入图片描述

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

🫵 小比特 大梦想

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

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

相关文章

利用Lora调整和部署 LLM

使用 NVIDIA TensorRT-LLM 调整和部署 LoRA LLM 大型语言模型 (LLM) 能够从大量文本中学习并为各种任务和领域生成流畅且连贯的文本&#xff0c;从而彻底改变了自然语言处理 (NLP)。 然而&#xff0c;定制LLM是一项具有挑战性的任务&#xff0c;通常需要完整的培训过程&#xf…

C++ 2024-4-1 作业

#include <iostream> using namespace std;class A { public:int a;A(int a):a(a){cout<<"A的有参构造"<<endl;} }; class B:virtual public A { public:int b;B(int a,int b):A(a),b(b){cout<<"B的有参构造"<<endl;} }; cl…

反截屏控制技术如何防止信息通过手机拍照泄漏?

反截屏控制技术为企业数据安全提供了重要的防护措施。通过以下几点&#xff0c;有效阻止了信息通过拍照等方式的泄漏&#xff1a; 反截屏控制开启&#xff0c;用户启动截屏操作时&#xff0c;允许非涉密内容截屏操作&#xff0c;但所有涉密内容窗口会自动隐藏&#xff0c;防止涉…

openstack云计算(一)————openstack安装教程,创建空白虚拟机,虚拟机的环境准备

1、创建空白虚拟机 需要注意的步骤会截图一下&#xff0c;其它的基本都是下一步&#xff0c;默认的即可 ----------------------------------------------------------- 2、在所建的空白虚拟机上安装CentOS 7操作系统 &#xff08;1&#xff09;、在安装CentOS 7的启动界面中…

Vue依赖注入,详细解析

Prop 逐级透传问题​ 通常情况下&#xff0c;当我们需要从父组件向子组件传递数据时&#xff0c;会使用 props。想象一下这样的结构&#xff1a;有一些多层级嵌套的组件&#xff0c;形成了一颗巨大的组件树&#xff0c;而某个深层的子组件需要一个较远的祖先组件中的部分数据。…

【JavaWeb】Day32.MySQL概述

什么是数据库 数据库&#xff1a;英文为 DataBase&#xff0c;简称DB&#xff0c;它是存储和管理数据的仓库。 像我们日常访问的电商网站京东&#xff0c;企业内部的管理系统OA、ERP、CRM这类的系统&#xff0c;以及大家每天都会刷的头条、抖音类的app&#xff0c;那这些大家所…

element-ui breadcrumb 组件源码分享

今日简单分享 breadcrumb 组件的源码实现&#xff0c;主要从以下三个方面&#xff1a; 1、breadcrumb 组件页面结构 2、breadcrumb 组件属性 3、breadcrumb 组件 slot 一、breadcrumb 组件页面结构 二、breadcrumb 组件属性 2.1 separator 属性&#xff0c;分隔符&#xff…

【洛谷 P8695】[蓝桥杯 2019 国 AC] 轨道炮 题解(映射+模拟+暴力枚举+桶排序)

[蓝桥杯 2019 国 AC] 轨道炮 题目描述 小明在玩一款战争游戏。地图上一共有 N N N 个敌方单位&#xff0c;可以看作 2D 平面上的点。其中第 i i i 个单位在 0 0 0 时刻的位置是 ( X i , Y i ) (X_i, Y_i) (Xi​,Yi​)&#xff0c;方向是 D i D_i Di​ (上下左右之一, 用…

零基础如何自学人工智能?推荐优秀的学习路径及方法

人工智能&#xff08;AI&#xff09;是一个广泛且复杂的领域&#xff0c;自学AI可能是一项艰巨的任务&#xff0c;但只要有兴趣和决心&#xff0c;这绝对是可能的。以下是一个零基础自学人工智能的学习路径&#xff0c;旨在帮助那些只有兴趣&#xff0c;但缺乏背景知识的人。 *…

[图解]DDD领域驱动设计伪创新-通用语言05

0 00:00:01,060 --> 00:00:04,370 甚至有的人把这个当成恩典 1 00:00:08,730 --> 00:00:11,500 他认为这个对技术人员有好处 2 00:00:13,010 --> 00:00:14,790 他掌握了主动权 3 00:00:15,730 --> 00:00:16,501 这样的话 4 00:00:16,501 --> 00:00:18,430 你…

【Android Studio】上位机-安卓系统手机-蓝牙调试助手

【Android Studio】上位机-安卓系统手机-蓝牙调试助手 文章目录 前言AS官网一、手机配置二、移植工程三、配置总结 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 AS官网 AS官网 一、手机配置 Android Studio 下真机调试 二、移植工程 Anro…

有时候在mac上使用IDEA无法访问系统里的文件,比如字体等。

有时候在mac上使用IDEA无法访问系统里的文件&#xff0c;比如字体等。 这里可以打开磁盘访问权限。

网络抓包专题

网络抓包原理 一. 什么是抓包&#xff1f; 在应用的开发调试中&#xff0c;查看软件实际运行时HTTP/HTTPS通信的请求数据和返回数据&#xff0c;从而分析问题的过程就叫做抓包。 通常我们说的抓包主要是分为两种&#xff1a; 使用 Wireshark 抓取传输层的 TCP/UDP 通信包。使…

ideaSSM 校园兼职招聘平台bootstrap开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea 开发 SSM 校园兼职招聘平台是一套完善的信息管理系统&#xff0c;结合SSM框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和数据库&#xff…

深度学习理论基础(二)深度神经网络DNN

目录 一、基础知识点Ⅰ 参数部分Ⅱ 模型部分 二、深度神经网络模型搭建1. 准备数据集2. 划分数据集3. 搭建模型4. 训练网络5. 测试网络6. 保存与导入模型 神经网络通过学习大量样本的输入与输出特征之间的关系&#xff0c;以拟合出输入与输出之间的方程&#xff0c;学习完成后&…

ndk ffmpeg

报错&#xff1a; 解决办法&#xff1a; 报错 解决办法&#xff1a;

js猜拳游戏

文章目录 1. 演示效果2. 分析思路3. 代码实现3.1. 方式一3.2. 方式二 1. 演示效果 2. 分析思路 获取玩家的出拳(获取按钮的标签体)获取电脑的出拳(随机数)比较二者的出拳&#xff0c;将比较的结果设置到对应的 span 标签中 3. 代码实现 3.1. 方式一 将点击事件进行动态绑定…

Python网络爬虫(四):b站评论

首先来看一下采集的数据格式: 本文不对数据采集的过程做探讨,直接上代码。首先要在程序入口处bvids列表内替换成自己想要采集的视频bvid号,然后将self.cookies替换成自己的(需要字典格式),代码可以同时爬取多个视频的评论,且爬取的评论较为完整,亲测有效: im…

股权激励和期权激励对比辨析

文章目录 概念定义 收益方式 风险评估 应用和分析 股权激励和期权激励&#xff0c;两者的区别是什么&#xff0c;本文就来梳理对比一下。 概念定义 股权激励&#xff0c;是指上市公司以本公司股票为标的&#xff0c;对其董事、高级管理人员及其他员工进行的长期性激励。取得…

二维相位解包理论算法和软件【全文翻译- 简单的路径依赖检验(2.6)】

将公式 2.33 【见前面的文章中】代入公式 2.2,可得 其中积分 代表与路径无关的解,只捕捉 φ 的非旋转成分,以及 代表包含 φ 旋转部分的路径依赖成分。 需要强调的是,F(r)(或 φ(r))中的旋转分量是二维相位解包中路径依赖的唯一来源。相位中的旋转成分是残差的原因。可…