【leetcode】拆解与整合:分治并归的算法逻辑

前言

🌟🌟本期讲解关于力扣的几篇题解的详细介绍~~~

🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客

🔥 你的点赞就是小编不断更新的最大动力                                       

🎆那么废话不多说直接开整吧~~

目录

📚️1.颜色分类

🚀1.1题目分析

🚀1.2思路分析

🚀1.3代码实现

📚️2.数组排序(双重解法)

🚀2.1题目分析

🚀2.2思路分析

2.2.1分治思想

2.3.2分治并归

🚀2.3代码实现

2.3.1分治思想 

2.3.2分治并归

📚️3.数组中第K个最大元素

🚀3.1题目分析

🚀3.2思路分析

3.2.1建立小根堆

3.2.2分治思想

🚀3.3代码实现

3.3.1建立小根堆思想

3.3.2分治思想

📚️4.总结

📚️1.颜色分类

🚀1.1题目分析

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

    必须在不使用库内置的 sort 函数的情况下解决这个问题。

    所以换一句话总结来说,就是将这里的数组进行排序,相邻的数字挨在一起;

     

    即如上图所示;

    🚀1.2思路分析

    这不就简单了吗,哈哈哈,小编的思路如下所示;

    第一种:直接通过八大排序,随便取一种进行排序即可;

    第二种:通过模拟哈希的方式,记录0下标有几个数,然后1下标有几个数,2下标有几个                      数,最后循环遍历输出就可以了;

    第三种:就是我们以分治的思想,将整个数组拆成三份;

     当然小编本期讲解的就是第三种思想方法;

    具体是思路:

    我们将数组分成三份,第一部分就是小于1的,第二部分就是等于1的,第三部分就是大于1的;

    那么使用双指针,分别在左右两端,指针i负责遍历数组,那么如果出现0就与left进行交换,1就直接跳过,2就与right进行交换;

    图示如下:

    注意:在这里我们为啥在num[ i ] 大于1后,为啥交换后,i不用增加呢?其实我们并不知道right指针所指的值,那么交换到i指针位置后,所以i指针需要继续进行判断;

    核心:

    num[ i ] < 1:left++,交换,i++;

    num[ i ] ==1:  i++;

    num[ i ] > 1:  right--,交换 

    🚀1.3代码实现

    代码如下所示:

    class Solution {public void sortColors(int[] nums) {int left = -1;int right = nums.length;for(int i = 0; i < right;){if(nums[i] == 0){swap(nums,++left,i);i++;}else if(nums[i] == 2){swap(nums,--right,i);}else{i++;}}}public void swap(int[] nums,int left,int right){int temp = nums[left];nums[left] = nums[right];nums[right] = temp;}
    }

    解释:注意这里的跳出循环条件,和初始化left与right的值,以及对于数组来说,这里的交换是如何进行的;

    📚️2.数组排序(双重解法)

    🚀2.1题目分析

    其实看题目就知道,这里就是对于数组进行排序的操作,如下所示:

    OK小编也不再多说了,直接进行入正题

    🚀2.2思路分析

    2.2.1分治思想

    其实这里的思路和上面进行分治的操作的思想是一致,将原始的数组进行分治三份进行后,元素就分为三个部分,其中等于某一个key值后,我们就不用管这个等于key的部分了,左边都是小于key的,右边都是大于key的,那么我们再对于这两个部分进行分治的操作;

    一直进行分治操作下,若只剩下两个数字,那么分治过后必定是有序的;那么总结:

    在不断的分治过程中,等于key的部分不用管,那么不等于key的两边部分一直进行分治操作,那么最终就会变得有序;

     

    那么这就是分治分三块思想可以完成次题的具体步骤;

    2.3.2分治并归

    这里的操作其实其实小编在很早的时候就已经讲解过了,就是快排的思想;

    不断的拆分,直到为一个数字的时候进行合并的操作,这里的合并的操作就是比较重要的;在每次合并的时候进行排序,那么在最终合成后,整个数组就是一个有序的数组;

    那么最终就是如上图所示,即可完成本此的排序操作;

    🚀2.3代码实现

    2.3.1分治思想 

    代码如下所示:

    class Solution {public int[] sortArray(int[] nums) {qsort(nums, 0 ,nums.length - 1);return nums;}public void qsort(int nums[],int l,int r){if(l>=r){return;}//随机进行取值的操作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){left++;swap(nums,i,left);i++;}else if(nums[i] == key){i++;}else if(nums[i] > key){right--;swap(nums,i,right);}}//排序完成后分为三部分[l,left][left+1,right-1][right,r]qsort(nums,l,left);qsort(nums,right,r);}public void swap(int nums[],int left,int right){int temp = nums[left];nums[left] = nums[right];nums[right] = temp;}
    }

    注意:这里的交换条件,以及边界的情况;

    2.3.2分治并归

    代码如下所示:

    class Solution {public int[] sortArray(int[] nums) {//归并排序操作mergeSort(nums,0,nums.length - 1);return nums;  }public void mergeSort(int[] nums,int left,int right){//进行边界判断if(left >= right){return;}//获取中点int mid = (right + left)/2;//此时[left,mid][mid + 1,right]mergeSort(nums,left,mid);mergeSort(nums,mid + 1 ,right);int[] temp = new int[right - left + 1];//合并数据操作int cur1 = left;int cur2 = mid + 1;int i = 0;while(cur1 <= mid && cur2 <= right){if(nums[cur1] <= nums[cur2]){temp[i] = nums[cur1];i++;cur1++;}else{temp[i] = nums[cur2];i++;cur2++;}}//判断是否还存在元素while(cur1 <= mid){temp[i] = nums[cur1];i++;cur1++;}while(cur2 <= right){temp[i] = nums[cur2];i++;cur2++;}//最后进行还原操作for(int j = left;j <= right;j++){nums[j] = temp[j-left];}}
    }

    注意在进行合并的时候,谁更小,谁就先放置在预备数组里;最终有一个数组是没有遍历完的,直接进行插入就可以了,前面有讲大家可以去看看;【数据结构】关于快速排序,归并排序,计数排序,基数排序,你到底了解多少???(超详解)_对比基数排序和快速排序-CSDN博客

    📚️3.数组中第K个最大元素

    🚀3.1题目分析

    给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

    请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

    你必须设计并实现时间复杂度为 O(n) 的算法解决此问题

    其实这里就是topk问题,那么小编就不多进行解释了

    🚀3.2思路分析

    其实这里的思路有几种:

    第一种:使用排序算法,在遍历寻找;

    第二种:建立小根堆,实现查找;

    第三种:使用分治的思想,分为三部分,来进行讨论;

     小编这里将讲解一下第一种和第二种算法思想:

    3.2.1建立小根堆

    具体的思路如下所示:

    按照K个长度的小根堆,然后将剩下的数字与堆顶元素进行比较,如果大于对顶元素,那么就将对顶元素删除,将这个大于对顶元素的值加入到堆中;

     最终堆顶的元素就是第K大的元素了;

    3.2.2分治思想

    思路如下:

    在我们分为三个部分后,那么第k大的元素就落在这三个部分中的一个;落在最右边,那么就去最右边去查找第K大的元素,落在中间直接返回,因为中间部分都是相等的数字;落在最左边,那么就去最左边找数字;

    如下所示:

     

    那么以上就是本题的结题思路;

    🚀3.3代码实现

    3.3.1建立小根堆思想

    代码如下所示:

    class Solution {public int findKthLargest(int[] nums, int k) {//实现小根堆PriorityQueue<Integer> minHeap = new PriorityQueue<>();for(int i = 0;i<k;i++){minHeap.offer(nums[i]);}//剩余元素for(int i = k;i<nums.length;i++){if(nums[i] > minHeap.peek()){minHeap.poll();minHeap.offer(nums[i]);}}return minHeap.peek();}

     当然这也是绝大多数的方法,也是比较简单的一种;

    3.3.2分治思想

    代码如下:

    class Solution {public int findKthLargest(int[] nums, int k) {// 快速选择算法return quickSort(nums, 0, nums.length - 1, k);}public int  quickSort(int nums[],int l,int r,int k){if(l == r){return nums[l];}//进行随机key值的获取int key = nums[new Random().nextInt(r - l + 1) + l];//进行变量的赋值int right = r + 1;int left = l - 1;int i = l;//进行选取while(i < right){if(nums[i] < key){left ++;swap(nums,i,left);i++;}else if(nums[i] == key){i++;}else if(nums[i] > key){right --;swap(nums,i,right);}}int b = right - left - 1;int c = r - right + 1;if(c >= k){return quickSort(nums,right,r,k);}else if(b+c >= k){return key;}else{return quickSort(nums,l,left,k-b-c);} }public void swap(int nums[],int left,int right){int temp = nums[left];nums[left] = nums[right];nums[right] = temp;}
    }

    解释:其实这里和前面数组的排序几乎是一致的,就是在进行分治的时候,需要进行判断在那个区间进行分治操作;

    📚️4.总结

    本期小编主要讲解了关于leetcode中的题目:

    颜色分类(75. 颜色分类 - 力扣(LeetCode))

    数组排序(912. 排序数组 - 力扣(LeetCode))

    TOPK问题(215. 数组中的第K个最大元素 - 力扣(LeetCode))

    主要的思想就是分治与并归的思想,大家可以多刷刷;

    🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!


    💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。

           😊😊  期待你的关注~~~

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

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

    相关文章

    wx162基于springboot+vue+uniapp的在线办公小程序

    开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

    陈宛汮签约2025火凤凰风赏大典全球形象大使

    原标题&#xff1a;陈宛汮签约2025火凤凰风赏大典全球形象大使 共工新闻社香港3月29日电 陈宛汮&#xff0c;华语原创女歌手。“星宝在闪耀”公益活动联合发起人&#xff0c;自闭症儿童康复推广大使。代表作:《荣耀火凤凰》《爱在醉千年》。 从2025年1月1日至2025年12月31日&a…

    【深度学习入门_机器学习理论】极致梯度提升原理(XGBoost)

    XGBoost&#xff08;eXtreme Gradient Boosting&#xff09;是一种高效、灵活且广泛应用的机器学习算法&#xff0c;属于梯度提升决策树&#xff08;Gradient Boosting Decision Tree, GBDT&#xff09; 的优化实现。它在分类、回归、排序等结构化/表格数据的预测任务中表现尤为…

    Oracle初识:登录方法、导入dmp文件

    目录 一、登录方法 以sys系统管理员的身份登录 &#xff0c;无需账户和密码 以账户密码的用户身份登录 二、导入dmp文件 方法一&#xff1a;PLSQL导入dmp文件 一、登录方法 Oracle的登录方法有两种。 以sys系统管理员的身份登录 &#xff0c;无需账户和密码 sqlplus / a…

    STM32F103_LL库+寄存器学习笔记01 - 梳理CubeMX生成的LL库最小的裸机系统框架

    《STM32 - 在机器人领域&#xff0c;LL库相比HAL优势明显》在机器人、自动化设备领域使用MCU开发项目&#xff0c;必须用LL库。 本系列笔记记录使用LL库的开发过程&#xff0c;首先通过CubeMX生成LL库代码&#xff0c;梳理LL库源码。通过学习LL库源码&#xff0c;弄清楚寄存器的…

    Vue3当中el-tree树形控件使用

    tree悬停tooltip效果 文本过长超出展示省略号 如果文本超出悬停显示tooltip效果 反之不显示 这里直接控制固定宽度限制 试了监听宽度没效果<template><el-treeshow-checkbox:check-strictly"true":data"data"node-key"id":props"…

    最大数字(java)(DFS实现)

    1.最大数字 - 蓝桥云课 因为N最大是10 的17次方&#xff0c; 所以可以利用字符串来处理输入的数字的每一位 并且是从高到低依次处理的 然后通过函数charAt(i)来获取第i位的字符 再减去‘0’就可以将字符转化为整型了 假设每一位数字都是x 然后通过两种操作 加或者减来操…

    04 单目标定实战示例

    看文本文,您将获得以下技能: 1:使用opencv进行相机单目标定实战 2:标定结果参数含义和数值分析 3:Python绘制各标定板姿态,查看图像采集多样性 4:如果相机画幅旋转90,标定输入参数该如何设置? 5:图像尺寸缩放,标定结果输出有何影响? 6:单目标定结果应用类别…

    手机销售终端MPR+LTC项目项目总体方案P183(183页PPT)(文末有下载方式)

    资料解读&#xff1a;手机销售终端 MPRLTC 项目项目总体方案 详细资料请看本解读文章的最后内容。在当今竞争激烈的市场环境下&#xff0c;企业的销售模式和流程对于其发展起着至关重要的作用。华为终端正处于销售模式转型的关键时期&#xff0c;波士顿 - 华为销售终端 MPRLTC …

    如何在 vue 渲染百万行数据,vxe-table 渲染百万行数据性能对比,超大量百万级表格渲染

    vxe-table 渲染百万行数据性能对比&#xff0c;超大量百万级表格渲染&#xff1b;如何在 vue 渲染百万行数据&#xff1b;当在开发项目时&#xff0c;遇到需要流畅支持百万级数据的表格时&#xff0c; vxe-table 就可以非常合适了&#xff0c;不仅支持强大的功能&#xff0c;虚…

    ubuntu24 部署vnc server 使用VNC Viewer连接

    前提条件 已创建一台Ubuntu 24.04(20.22通用)操作系统的云服务器&#xff0c;并且为云服务器绑定弹性公网IP&#xff0c;确保可以连接互联网。 已在本地PC安装VNC Viewer客户端。 操作步骤 服务器内安装vnc server以及桌面环境 apt update sudo apt install xfce4 xfce4-…

    【数据结构】栈 与【LeetCode】20.有效的括号详解

    目录 一、栈1、栈的概念及结构2、栈的实现3、初始化栈和销毁栈4、打印栈的数据5、入栈操作---栈顶6、出栈---栈顶6.1栈是否为空6.2出栈---栈顶 7、取栈顶元素8、获取栈中有效的元素个数 二、栈的相关练习1、练习2、AC代码 个人主页&#xff0c;点这里~ 数据结构专栏&#xff0c…

    06-SpringBoot3入门-常见注解(简介)

    1、Controller ResponseBody Controller是Spring MVC 中的注解&#xff0c;负责处理 HTTP 请求。 ResponseBody是Spring MVC 中的注解&#xff0c;用于直接将方法的返回值作为 HTTP 响应体。 2、RestController RestController Controller ResponseBody 3、RequestMappin…

    工作记录 2017-03-10

    工作记录 2017-03-10 序号 工作 相关人员 1 修改邮件上的问题。 更新RD服务器。 郝 更新的问题 1、修改了payment detail和patient insurance的health plan的输入方式。 2、new payment detail时&#xff0c;增加了allowable的处理。 3、选择payer的窗体&#xff0c;增…

    MySQL数据库和表的操作

    #使用数据库 use 数据库名; # 查询当前数据库是哪个数据库 select database(); 查看数据库版本 SELECT VERSION(); 查看当前用户 SELECT USER(); 查看所有用户() SELECT User,Host,Password FROM mysql.user;数据库 MySQL自带数据库&#xff1a; Information_schema: 主要存储…

    lxd-dashboard 图形管理LXD/LXC

    前言 LXD-WEBGUI是一个完全用AngularJS编写的Web应用程序,无需应用服务器、数据库或其他后端服务支持。只需要简单地托管静态HTML和JavaScript文件,就能立即投入使用。这个项目目前处于测试阶段,提供了直观的用户界面,帮助用户便捷地管理和控制LXD实例。 安装lxd-dashboa…

    [GESP202503 C++一级题解]:B4257:图书馆里的老鼠

    [GESP202503 C++一级题解]:B4257:图书馆里的老鼠 题目描述 图书馆里有 n n n 本书,不幸的是,还混入了一只老鼠,老鼠每 x x x 小时能啃光一本书,假设老鼠在啃光一本书之前,不会啃另一本。请问 y y y 小时后图书馆里还剩下多少本完整的书。 输入格式 三行,第一行一…

    从零构建大语言模型全栈开发指南:第二部分:模型架构设计与实现-2.2.2文本生成逻辑:Top-k采样与温度控制

    👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 2.2.2 文本生成逻辑:Top-k采样与温度控制1. 文本生成的核心挑战与数学框架1.1 自回归生成的基本流程2. `Top-k`采样原理与工程实现2.1 数学定义与算法流程2.2 PyTorch实现优化3. 温度控制的数学本质与参…

    Unity中实现UI的质感和圆角

    质感思路有两种&#xff1a; 一种是玻璃质感的做法&#xff0c;抓取UI后面的图像做模糊&#xff08;build是GrabPass&#xff0c;urp抓图像我有写过在往期文章&#xff09;&#xff0c;这个方式网络上有很多就不写了&#xff1b; 另外一种是使用CubeMap的方式去模拟质感&…

    [异步监听事件、异步绑定属性]通过vue的this.$refs.组件.$props和.$on实现异步绑定组件属性和事件监听

    child.vue <template><div><el-button type"primary" click.stop"$emit(get, data)">点击传参</el-button></div> </template> <script> export default { name: "child", props: ["data"…