【算法百题】专题七_分治快排_专题八_分治归并
文章目录
- 前言
- 分治快排题:
- 043. [颜⾊分类(medium)](https://leetcode.cn/problems/sort-colors/description/)
- 分析
- 044. [快速排序(medium)](https://leetcode.cn/problems/sort-an-array/description/)
- 分析
- 045. [快速选择算法(medium)](https://leetcode.cn/problems/kth-largest-element-in-an-array/description/)
- 分析
- 046. [仓库管理](https://leetcode.cn/problems/zui-xiao-de-kge-shu-lcof/description/)
- 分析
- 分治归并题
- 047. [归并排序(medium)](https://leetcode.cn/problems/sort-an-array/description/)
- 分析
- 048. [数组中的逆序对(hard)](https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/description/)
- 分析
- 049. [计算右侧⼩于当前元素的个数(hard)](https://leetcode.cn/problems/count-of-smaller-numbers-after-self/description/)
- 分析
- 050. [计算右侧⼩于当前元素的个数(hard)](https://leetcode.cn/problems/reverse-pairs/description/)
- 分析
- 总结
前言
分治顾名思义,就是分而治之,分治是一个思路,并不是由暴力优化而来的,还是因为暴力解的重复比较太多,我们可以将大问题划分为小问题(当然不是无厘头的划分),每次分割后,子问题的规模呈指数级缩小(理想情况下减半),总操作次数从 O(n^2) 降至 O(nlogn).
分治快排题:
043. 颜⾊分类(medium)
分析
class Solution {
public:void sortColors(vector<int>& nums) {int left = -1,right = nums.size();int i = 0;while(i < right){if(nums[i] < 1) swap(nums[++left],nums[i++]);else if(nums[i] > 1) swap(nums[--right],nums[i]);else i++;}}
};
044. 快速排序(medium)
分析
class Solution {
public:vector<int> sortArray(vector<int>& nums) {srand(time(nullptr));qsort(nums,0,nums.size()-1);return nums;}void qsort(vector<int>& nums,int l,int r){//3.然后再写"归"的逻辑,如果只有一个值,一个值也是有序的,那么直接返回,不用排了.//if(r - l + 1 == 1) return; 逻辑没错,但是有可能出现l 比 r大的情况if(l >= r) return;//1.这里分治用的是快排的方向,所以先将我们的数组进行划分,然后再递归子区间.int key = getRandNum(nums,l,r); //随机找一个数作为key,避免有序情况的爆栈int i = l;int left = l - 1,right = r + 1;while(i < right) //然后开始将数组根据key值进行划分{if(nums[i] < key) swap(nums[++left],nums[i++]);else if(nums[i] > key) swap(nums[--right],nums[i]);else i++;}//2.递归递归,当然要先写向深处"递"的逻辑.qsort(nums,l,left);qsort(nums,right,r);}int getRandNum(vector<int>& nums,int l,int r){int x = rand();return nums[x % (r - l + 1) + l];}
};
045. 快速选择算法(medium)
分析
class Solution {
public:int findKthLargest(vector<int>& nums, int k) {srand(time(nullptr));return qsort(nums,0,nums.size()-1,k);}int qsort(vector<int>& nums,int l,int r,int k){if(l >= r) return nums[l];int key = getRandpm(nums,l,r);int i = l;int left = l - 1,right = r + 1;while(i < right){if(nums[i] < key) swap(nums[++left],nums[i++]);else if(nums[i] > key) swap(nums[--right],nums[i]);else i++;}if(r - right + 1 >= k) return qsort(nums,right,r,k); //优化再递归思路这里,不用全部递归,可以根据大概的左右子区间的元素个数,判断一下我们的topK最终会在什么区间,时间复杂度是O(N).else if(r - left >= k) return key;else return qsort(nums,l,left,k - (r - left));}int getRandpm(vector<int>& nums,int l,int r){return nums[rand() % (r - l + 1) + l];}
};
046. 仓库管理
分析
class Solution {
public:vector<int> inventoryManagement(vector<int>& stock, int cnt) {srand(time(nullptr));qsort(stock,0,stock.size() - 1,cnt);return {stock.begin(),stock.begin() + cnt};}void qsort(vector<int>& stock,int l,int r,int cnt){if( l >= r) return;int key = getRandom(stock,l,r);int i = l,left = l - 1,right = r + 1;while(i < right){if(stock[i] < key) swap(stock[++left],stock[i++]);else if(stock[i] > key) swap(stock[--right],stock[i]);else i++;}int a = left - l + 1,b = right - left - 1,c = r - right + 1; //我们快排本来就是在原数组上面做操作,所以走完逻辑其实原数组也就拍好了if(a >= cnt) qsort(stock, l,left,cnt);else if(a + b >= cnt) return ;else qsort(stock, right,r,cnt - a - b);}int getRandom(vector<int>& stock,int l,int r){return stock[l + rand() % (r - l + 1)];}
};
分治归并题
047. 归并排序(medium)
分析
class Solution {vector<int> tmp; //我们合并的过程中,需要一个单独的容器暂时存储.
public:vector<int> sortArray(vector<int>& nums) {tmp.resize(nums.size());mergeSort(nums,0,nums.size()-1);return nums;}void mergeSort(vector<int>& nums,int left,int right){//2.然后写"归"的逻辑,不然即使"递"到了最深处,即[l,r]区间的只有一个数据时,也不会停下.if(left >= right) return; //只有一个数据时,也是有序的.//1.从数组的中间开始划分,先"递"到最深处.int mid = (right + left) >> 1; mergeSort(nums,left,mid);mergeSort(nums,mid + 1,right);//3.然后开始每个组 合并的逻辑int x = left;int i = left,j = mid + 1;while(i <= mid && j <= right){if(nums[i] <= nums[j]) tmp[x++] = nums[i++];else tmp[x++] = nums[j++];}while(i <= mid) //如果小组里面还有没合并完的大组,那么,直接放入tmp.{tmp[x++] = nums[i++];}while(j <= right){tmp[x++] = nums[j++];}//将tmp数据同步回原数组,那么我们的一次合并就完成了.for(int i = left;i <= right;i++){nums[i] = tmp[i]; }}
};
048. 数组中的逆序对(hard)
分析
class Solution
{int tmp[50010];
public:int reversePairs(vector<int>& record) {return mergeSort(record,0,record.size()-1);}int mergeSort(vector<int>& nums,int left,int right){//2.写"归"的逻辑,让它在停在有两个最小组的层.方便我们对两个最小组中的值做刚开始的逆序对判断.if(left >= right) return 0;int ret = 0;//1.先"递"到最小int mid = (left + right) >> 1;ret += mergeSort(nums,left,mid);ret += mergeSort(nums,mid + 1,right);//3.合并同时做判断,找到所有符合的逆序对int cur1 = left,cur2 = mid + 1,i = left;while(cur1 <= mid && cur2 <= right){if(nums[cur2] >= nums[cur1]){tmp[i++] = nums[cur1++];}else{ret += mid - cur1 + 1;tmp[i++] = nums[cur2++];}}while(cur1 <= mid) tmp[i++] = nums[cur1++];while(cur2 <= right) tmp[i++] = nums[cur2++];//4.将tmp中排序好的顺序数组,覆盖回原数组.for(int i = left;i <= right;i++){nums[i] = tmp[i];}return ret;}
};
049. 计算右侧⼩于当前元素的个数(hard)
分析
class Solution {vector<int> ret;vector<int> index;int tmp[100010];int tmpIndex[100010];
public:vector<int> countSmaller(vector<int>& nums){int n = nums.size();ret.resize(n,0);index.resize(n);for(int i = 0;i < n;i++)index[i] = i;mergeSort(nums,0,n-1);return ret;}void mergeSort(vector<int>& nums,int left,int right){if(left >= right) return;int mid = (left + right) >> 1;mergeSort(nums,left,mid);mergeSort(nums,mid + 1,right);int cur1 = left,cur2 = mid + 1,i = left;while(cur1 <= mid && cur2 <= right){if(nums[cur1] > nums[cur2]){ret[index[cur1]] += right - cur2 + 1;tmp[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}else{tmp[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}}while(cur1 <= mid) {tmp[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}while(cur2 <= right) {tmp[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}//将临时的下标数组和原数组都同步回去.for(int i = left;i <= right;i++){nums[i] = tmp[i];index[i] = tmpIndex[i];}}
};
050. 计算右侧⼩于当前元素的个数(hard)
分析
class Solution {int tmp[50010];
public:int reversePairs(vector<int>& nums) {return mergeSort(nums,0,nums.size() - 1);}int mergeSort(vector<int>& nums,int left,int right){//2."归"if(left >= right) return 0;int ret = 0;//1.先"递"int mid = (left + right) >> 1;ret += mergeSort(nums,left,mid);ret += mergeSort(nums,mid + 1,right);//2.1统计所有翻转对.int cur1 = left,cur2 = mid + 1,i = left;while(cur2 <= right){while(cur1 <= mid && nums[cur1] / 2.0 <= nums[cur2]) cur1++;if(cur1 > mid) break;ret += mid - cur1 + 1;cur2++;}cur1 = left,cur2 = mid + 1;//3.排序并判断翻转对while(cur1 <= mid && cur2 <= right){if(nums[cur1] <= nums[cur2]){tmp[i++] = nums[cur1++];}else{tmp[i++] = nums[cur2++];}}//4.将没有排完的排完while(cur1 <= mid){tmp[i++] = nums[cur1++];}while(cur2 <= right){tmp[i++] = nums[cur2++];}//5.将排好的数组覆盖原数组.for(int i = left;i <= right;i++){nums[i] = tmp[i];}return ret;}
};
总结
分治的思路,远不止这两种,将问题划分小也不总是针对一个数组的(动规也是分治思想的延伸),但是本专题,针对数组的划分,尽量理解"我们是一名老师,让孩子们站队"的例子.
本文章为作者的笔记和心得记录,顺便进行知识分享,有任何错误请评论指点:)。
相关文章:
【算法百题】专题七_分治快排_专题八_分治归并
文章目录 前言分治快排题:043. [颜⾊分类(medium)](https://leetcode.cn/problems/sort-colors/description/)分析 044. [快速排序(medium)](https://leetcode.cn/problems/sort-an-array/description/)分析 045. [快速…...
DOM4J解析XML, 修改xml的值
1. 引入pom依赖 <dependency><groupId>org.dom4j</groupId><artifactId>dom4j</artifactId><version>2.1.3</version> </dependency> 2. 解析xml, 修改xml节点的值 import org.apache.commons.io.IOUtils; import org.dom4…...
3.16[A]FPGA
FPGA的工作原理是通过配置存储器中的数据来控制可编程逻辑单元和互连资源,从而实现用户定义的逻辑功能。用户可以通过硬件描述语言(HDL)编写代码,然后通过综合、映射、布局布线等步骤生成配置数据,最后将这些数据加载到…...
ssh转发笔记
工作中又学到了,大脑转不过来 现有主机A,主机B,主机C A能访问B,B能访问C,A不能访问C C上80端口有个服务,现在A想访问这个服务,领导让用ssh转发,研究半天没找到理想的语句…...
使用OBS进行webRTC推流参考
参考腾讯云官方文档: 云直播 OBS WebRTC 推流_腾讯云 说明非常详细,分为通过WHIP和OBS插件的形式进行推流。 注意:通过OBS插件的形式进行推流需要使用较低的版本,文档里有说明,需要仔细阅读。...
(链表)面试题 02.07. 链表相交
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意,函数返回结果后ÿ…...
Python----数据可视化(Pyecharts三:绘图二:涟漪散点图,K线图,漏斗图,雷达图,词云图,地图,柱状图折线图组合,时间线轮廓图)
1、涟漪特效散点图 from pyecharts.globals import SymbolType from pyecharts.charts import EffectScatter from pyecharts.faker import Faker from pyecharts import options as opts from pyecharts.globals import ThemeType # 绘制图表 es (EffectScatter(init_optsop…...
正则表达式:贪婪匹配与非贪婪匹配
正则表达式:贪婪匹配与非贪婪匹配 非贪婪匹配 .*?这三个字符的组合就是非贪婪匹配,意思是匹配任意字符直到遇到第一个后面指定的字符,比如.*?_就表示匹配任意字符直到碰到下划线,还可以组合^来表示从头匹配,比如^.*?_就是从头…...
IP风险度自检,互联网的安全“指南针”
IP地址就像我们的网络“身份证”,而IP风险度则是衡量这个“身份证”安全性的重要指标。它关乎着我们的隐私保护、账号安全以及网络体验,今天就让我们一起深入了解一下IP风险度。 什么是IP风险度 IP风险度是指一个IP地址可能暴露用户真实身份或被网络平台…...
数据结构与算法-图论-拓扑排序
前置芝士 概念 拓扑排序(Topological Sorting)是对有向无环图(DAG,Directed Acyclic Graph)的顶点进行排序的一种算法。它将图中的所有顶点排成一个线性序列,使得对于图中的任意一条有向边 (u, v)&#x…...
Gan网络公式了解
Gan网络 生成器和判别器是亦敌亦友的关系 对于生成模型,损失函数很难定义->所以我们可以将生成模型的输出交给判别模型进行处理,来分辨好坏。 生成器的损失是通过判别器的输出来计算的,而判别器的输出是一个概率值,我们可以通过…...
解决linux mysql命令 bash: mysql: command not found 的方法
首先得知道mysql命令或mysqladmin命令的完整路径 比如mysql的路径是: /usr/local/mysql/bin/mysql,我们则可以这样执行命令: ln -s /usr/local/mysql/bin/mysql /usr/bin © 著作权归作者所有,转载或内容合作请联系作者 喜欢的朋友记得点…...
微服务存在的问题及解决方案
微服务存在的问题及解决方案 1. 存在问题 1.1 接口拖慢 因为一个接口在并发时,正好执行时长又比较长,那么当前这个接口占用过多的 Tomcat 连接,导致其他接口无法即时获取到 Tomcat 连接来完成请求,导致接口拖慢,甚至…...
【css酷炫效果】纯CSS实现立体纸张折叠动效
【css酷炫效果】纯CSS实现悬浮阴影扩散交互 缘创作背景html结构css样式完整代码基础版进阶版(3d 悬浮效果) 效果图 通过CSS box-shadow与transition属性实现悬浮阴影扩散交互,为元素添加细腻的悬浮反馈。 想直接拿走的老板,链接放在这里:htt…...
案例5_1:单位数码管显示0
文章目录 文章介绍效果图仿真图5_1放置单位数码管 代码5_1.c 文章介绍 效果图 仿真图5_1 复制案例1_2的仿真图,在此基础上修改 注意:栅格大小需要缩小 放置单位数码管 代码5_1.c #include <reg52.h>#define uchar unsigned char #define uint un…...
Linux centos7误删/boot拯救方法
1.进入救援模式 插入CentOS 7安装光盘,重启系统。在开机时按BIOS设置对应的按键(通常是F2等),将启动顺序调整为CD - ROM优先。 系统从光盘启动后,选择“Troubleshooting”,然后选择“Rescue a CentOS s…...
操作系统八股文整理(一)
操作系统八股文整理 一、进程和线程的区别二、进程与线程的切换过程一、进程切换进程切换的步骤: 二、线程切换线程切换的步骤: 三、进程切换与线程切换的对比四、上下文切换的优化 三、系统调用一、系统调用的触发二、从用户空间切换到内核空间三、执行…...
20250317笔记本电脑在ubuntu22.04下使用acpi命令查看电池电量
20250317笔记本电脑在ubuntu22.04下使用acpi命令查看电池电量 2025/3/17 18:05 百度:ubuntu查看电池电量 百度为您找到以下结果 ubuntu查看电池电量 在Ubuntu操作系统中,查看电池电量通常可以通过命令行或者图形界面来完成。下面是一些常见的方法&…...
蓝桥杯备考----模拟算法 phone number
嗯。这道题可以在两个和三个数字加-,我们只要随便输出一个奏行 那么!我们规范一下,我们尽可能的只在两个数字之间加,但是如果一共奇数个的话,我们就让最后三个成一组,也就是说,我们用的是个小贪…...
【数据分享】2000—2024年我国省市县三级逐月归一化植被指数(NDVI)数据(Shp/Excel格式)
之前我们分享过2000—2024年逐月归一化植被指数(NDVI)栅格数据(可查看之前的文章获悉详情),该数据来源于NASA定期发布的MOD13A3数据集!很多小伙伴拿到数据后反馈栅格数据不太方便使用,问我们能不…...
算法基础篇(蓝桥杯常考点)
算法基础篇 前言 算法内容还有搜索,数据结构(进阶),动态规划和图论 数学那个的话大家也知道比较难,放在最后讲 这期包含的内容可以看目录 模拟那个算法的话就是题说什么写什么,就不再分入目录中了 注意事…...
Python中使用vlc库实现视频播放功能
文章目录 前言1. 环境准备1.1Python安装1.2选择Python开发环境1.3安装必要库 2. 基础播放示例3. 常用播放控制功能4. 事件监听5. 播放网络流媒体6. 结合 GUI 库制作视频播放器(以 Tkinter 为例) 前言 本教程主要包含打开文件、播放和停止按钮࿰…...
蓝桥杯真题——洛谷 Day10 并查集(枚举)
目录 P8651 [蓝桥杯 2017 省 B] 日期问题 P8635 [蓝桥杯 2016 省 AB] 四平方和 P8651 [蓝桥杯 2017 省 B] 日期问题 思路: 使用scanf读入,枚举从1960到2059,若符合题目形式,加入答案, 从小到大输出:存入结…...
微前端 无界wujie
开发环境配置: Node.js 版本 < 18.0.0 pnpm 脚手架示例模版基于 pnpm turborepo 管理项目 如果您的当前环境中需要切换 node.js 版本, 可以使用 nvm or fnm 进行安装. 以下是通过 nvm 或者nvs 安装 Node.js 16 LTS 版本 nvs安装教程 https://blog.csdn.net/glorydx/artic…...
Linux应用:程序运行
kill kill命令的这种用法是向指定的进程发送特定信号编号的信号。信号在操作系统中是一种软件中断机制,用于通知进程发生了某种特定事件或要求进程执行特定操作。 kill - 信号编号 进程 ID 信号编号的含义:不同的信号编号代表不同的事件或操作。例如…...
【公务员考试】高效备考指南
高效备考指南:从计划制定到心态调整的全面攻略 公务员考试竞争激烈,备考过程既需要科学规划,也需要持之以恒的努力。结合多位高分考生的经验与专业机构的指导,本文整理了一套系统化的备考策略,涵盖目标设定、学习方法…...
基于SpringBoot+Vue3实现的宠物领养管理平台功能一
一、前言介绍: 1.1 项目摘要 随着社会经济的发展和人们生活水平的提高,越来越多的人开始关注并参与到宠物领养中。宠物已经成为许多家庭的重要成员,人们对于宠物的关爱和照顾也日益增加。然而,传统的宠物领养流程存在诸多不便&a…...
ens33没有分配到IPV4问题
方法一:手动为 ens33 接口分配 IP 地址 你能够借助 ip 命令手动给 ens33 接口分配 IP 地址。不过这种方式在系统重启之后就会失效。 步骤 查看网络信息 先查看一下当前网络的子网信息,例如网关地址和子网掩码等,你可以通过路由器管理界面或…...
SpringCloud 学习笔记2(Nacos)
Nacos Nacos 下载 Nacos Server 下载 | Nacos 官网 下载、解压、打开文件: 更改 Nacos 的启动方式 Nacos 的启动模式默认是集群模式。在学习时需要把他改为单机模式。 把 cluster 改为 standalone,记得保存! 启动startup.cmd Ubuntu 启动…...
Blender-MCP服务源码4-初始化项目解读
Blender-MCP服务源码4-初始化项目解读 上篇文章针对Blender开发框架完成了一个基础模板的搭建,并在Blender中成功进行了运行,那这个初始化项目中是如何进行页面效果呈现的,尝试手动进行功能精简来拆解项目代码 1-核心知识点 1)如…...








