算法---分治(归并排序)

在这里插入图片描述

T04BF

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

🫵 小比特 大梦想

此篇文章与大家分享分治算法关于归并排序的专题
对于归并排序在我个人主页专栏 <排序> 有详细的介绍
如果有不足的或者错误的请您指出!

1.归并排序

题目: 排序数组

1.1解析

关于归并排序的解析在我的个人主页<排序>专栏有详细的解释,理解归并排序对本专题的其他题目格外重要,一定要先理解归并排序的原理
本文直接画图说明:
在这里插入图片描述

1.2题解

public class Test4 {int[] tmp;//将tmp数组设置为类属性时间复杂度更低public int[] sortArray(int[] nums) {tmp = new int[nums.length];mergeSort(nums,0,nums.length-1);return nums;}private void mergeSort(int[] nums,int left,int right){if(left >= right){return;}int mid = left + (right-left)/2;mergeSort(nums,left,mid);mergeSort(nums,mid+1,right);int i = 0;int cur1 = left;int cur2 = mid+1;while(cur1 <= mid && cur2 <= right){tmp[i++] = nums[cur1] > nums[cur2] ? nums[cur2++] : nums[cur1++];}while(cur1 <= mid){tmp[i++] = nums[cur1++];}while(cur2 <= right){tmp[i++] = nums[cur2++];}for(int j = left; j <= right; j++){nums[j] = tmp[j-left];}}
}

2.数组中的逆序对

题目:数组中的逆序对

2.1解析:

如果我们通过暴力解法,就是两个两个枚举,但是时间复杂度太高了,在本题会超时
我们转变一下思路:
在这里插入图片描述
如果我们把数组划分维如图所示的两段区间,假设左区间的逆序对的数量为a,右边的逆序对的数量为b,再加上枚举左边一个右边一个元素的所有逆序对的情况为c,那么总逆序对的情况就是a + b + c;而左边区间和右边区间又各自可以分成两段区间…
举个具体例子:
在这里插入图片描述
如图所示,我们用count来记录逆序对的个数,那么最后一层9 和 7,就是1组逆序对,count = 1; 9 7 和 5,可以组成 (9,5)和 (7,5),那么count = 3;
4和6不能组成逆序对;9 7 5 和 4 6,可以组成(9,4),(9,6),(7,4),(7,6),(5,4) ,那么count = 8
而上述每次分解成两段区间的过程不就是我们归并排序的分解过程嘛??
再者说,好像我们这样子分,到头来还是需要一一枚举,好像时间复杂度并没有很大的提示.但是我们实际上会发现一个细节:
我们在一一枚举的过程中并不关心左区间元素的顺序,也不关心右区间元素的顺序,我们每次只需要关心相对于左边的某个元素,在右边有多少个比这个元素小即可
那么我们就可以利用归并排序,将左右区间排序好
在这里插入图片描述
假设这是我们某段已经分别排好序的左右区间,排完序后我们找逆序对的时间复杂度就很低了
我们用变量cur2来遍历右区间,用变量cur1来遍历左区间
那么在定住cur2的时候,我们只需在左边从左到右找到第一个比2大的,就是3,那么,在左区间内3以后的所有数字,都可以和右区间的2组成逆序对,这样我们一下子就找出很多逆序对,不再需要一一枚举;接下来cur2++,但是cur1不需要回头重新从1开始遍历,因为我们的区间是递增的,而1 < 2,1就必然小于3,这就是排序给我们带来的很多好处
而当我们回顾一下归并排序的过程:我们也是用变量cur2来遍历右区间,用变量cur1来遍历左区间,当nums[cur1] <= nums[cur2]的时候,cur1++;反之cur2++,这不就恰好和我们上面分析的过程一模一样嘛???
因此我们只需要将上面的找逆序对的过程穿插在归并排序中间即可!不会给原归并排序带来时间复杂度的增加,因此时间复杂度还是O(N logN)!

理解完上面后,我们来拓展一个点
我们上面的数组是递增的,但是如果是递减呢??
在这里插入图片描述
那么此时我们应该是定住左边的元素,在右边找到第一个比这个元素小的,那么找到的这个元素之后的所有元素,都能和左边这个元素组成逆序对

2.2题解:

class Solution {private  int count = 0;private  int[] tmp;public  int reversePairs(int[] record) {tmp = new int[record.length];mergeSort(record,0,record.length-1);return count;}private  void mergeSort(int[] record,int left,int right){if(left >= right){return;}int mid = left + (right-left)/2;mergeSort(record,left,mid);mergeSort(record,mid+1,right);int cur1 = left;int cur2 = mid+1;int k = 0;while(cur1 <= mid && cur2 <= right){if(record[cur1] > record[cur2]){tmp[k++] = record[cur2++];count += mid - cur1 + 1;}else{tmp[k++] = record[cur1++];}}while(cur1 <= mid){tmp[k++] = record[cur1++];}while(cur2 <= right){tmp[k++] = record[cur2++];}for(int i = left; i <= right; i++){record[i] = tmp[i-left];}}
}

3.计算右侧小于当前元素的个数

题目:计算右侧小于当前元素的个数

3.1解析

实际上和我们上一道题的原理是一模一样的,但是这道题要我们返回的是数组就给我们带来了一定的难度
即题目要求我们返回的是数组,数组中存储的是给定数组对应元素的右侧小于当前元素的个数,而由于我们的原数组在归并排序中是一直在变的
解决方法就是哈希思想,但是我们采用哈希表,因为数组中可能会存在重复元素;
我们可以构建一个index数组,用来映射给定数组的下标,.当给定数组变了的时候,我们的index也要跟着变

3.2 题解

class Solution {int[] ret;int[] tmp;int[] tmpIndex;int[] index;public List<Integer> countSmaller(int[] nums) {ret = new int[nums.length];tmp = new int[nums.length];tmpIndex = new int[nums.length];index = new int[nums.length];for(int i = 0; i < index.length; i++){index[i] = i;}mergeSort(nums,0,nums.length-1);List<Integer> list = new ArrayList<>();for(int x : ret){list.add(x);}return list;}private void mergeSort(int[] nums,int left,int right){if(left >= right){return;}int mid = left + (right - left)/2;mergeSort(nums,left,mid);mergeSort(nums,mid+1,right);int cur1 = left;int cur2 = mid + 1;int k = 0;while(cur1 <= mid && cur2 <= right){if(nums[cur2] >= nums[cur1]){tmp[k] = nums[cur2];tmpIndex[k++] = index[cur2++];}else{ret[index[cur1]] += right - cur2 + 1;tmp[k] = nums[cur1];tmpIndex[k++] = index[cur1++];}}while (cur1 <= mid){tmp[k] = nums[cur1];tmpIndex[k++] = index[cur1++];}while(cur2 <= right){tmp[k] = nums[cur2];tmpIndex[k++] = index[cur2++];}for(int i = left; i <= right; i++){nums[i] = tmp[i-left];index[i] = tmpIndex[i-left];}}
}

4.翻转对

题目:翻转对

4.1解析

大体思路还是和我们前两题的思路是一样的,但是有一点特别的就是,.我们前两道题,无论是找逆序对还是找比当前元素小的个数,实际上都是单纯的两个数比大小,恰好和归并排序的过程吻合
但是我们这道题要比较的是两倍的关系,因此我们需要"合并"两次,第一次合并实际上并不是真正的合并,而是判断进行比较;第二次才是真正的合并

4.2题解

class Solution {int[] tmp;int count = 0;public int reversePairs(int[] nums) {tmp = new int[nums.length];merseSort(nums,0,nums.length-1);return count;}private void merseSort(int[] nums,int left,int right){if(left >= right){return;}int mid = left + (right - left) / 2;merseSort(nums,left,mid);merseSort(nums,mid+1,right);int cur1 = left;int cur2 = mid + 1;while(cur1 <= mid && cur2 <= right){while(cur2 <= right && nums[cur1] / 2.0 <= nums[cur2]){cur2++;}count += right - cur2 + 1;cur1++;}cur1 = left;cur2 = mid+1;int k = 0;while(cur1 <= mid && cur2 <= right){tmp[k++] = nums[cur1] > nums[cur2] ? nums[cur1++] : nums[cur2++];}while(cur1 <= mid){tmp[k++] = nums[cur1++];}while(cur2 <= right){tmp[k++] = nums[cur2++];}for(int i = left; i <= right; i++){nums[i] = tmp[i-left];}}
}

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

在这里插入图片描述

T04BF

🫵 小比特 大梦想

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

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

相关文章

如何编写属于自己的第一个exp

0x00 前言 在我们找到一个漏洞之后&#xff0c;可能会想着去fofa上搜语法进而扩大战果&#xff0c;而有些漏洞利用起来十分繁琐&#xff0c;这时候就需要一个exp来批量帮我们进行扫描工作&#xff0c;接下来就介绍一下如何进行exp的编写&#xff0c;这个过程中最重要的还是体现…

【Pt】马灯贴图绘制过程 04-玻璃脏迹

目录 效果 步骤 一、透明玻璃 二、烟熏痕迹 三、粗糙 四、浮尘 效果 步骤 一、透明玻璃 1. 打开纹理集设置&#xff0c;着色器链接选择“新的着色器链接” 在着色器设置中可以看到此时名称为“Main shader &#xff08;Copy&#xff09;” 这里修改名称为“玻璃” 在…

设计模式总结-外观模式(门面模式)

外观模式 模式动机模式定义模式结构外观模式实例与解析实例一&#xff1a;电源总开关实例二&#xff1a;文件加密 模式动机 引入外观角色之后&#xff0c;用户只需要直接与外观角色交互&#xff0c;用户与子系统之间的复杂关系由外观角色来实现&#xff0c;从而降低了系统的耦…

基于FPGA的图像累积直方图verilog实现,包含tb测试文件和MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 Vivado2019.2 matlab2022a 3.部分核心程序 timescale 1ns / 1ps // // Company: // Engineer: // // Design Name: // …

Docker 容器编排技术解析与实践

探索了容器编排技术的核心概念、工具和高级应用&#xff0c;包括 Docker Compose、Kubernetes 等主要平台及其高级功能如网络和存储管理、监控、安全等。此外&#xff0c;文章还探讨了这些技术在实际应用中的案例&#xff0c;提供了对未来趋势的洞见。 一、容器编排介绍 容器编…

美化异常traceback信息,提升调试效率的实用工具

文章目录 Python pretty_errors库使用教程1. 安装pretty_errors库2. 环境要求3. 使用pretty_errors库4. 配置全局可用&#xff08;可选&#xff09;5. 效果对比 Python pretty_errors库使用教程 pretty_errors是一个Python库&#xff0c;用于美化异常的traceback信息&#xff…

C++运算符重载如何模拟数学表达式,或模拟Python sympy和numpy

在人工智能数学基础一书中&#xff0c;下面是一题Python求函数极限的例子&#xff1a; 【例2.6】使用Python编程求 lim( x → 1) (x^2 - 1 / x - 1) ————————————————————————————————————————— import sympy from sympy import oo…

Android Studio学习8——点击事件

在xml代码中绑定 在java代码中绑定 弹出一个toast 随机&#xff0c;数组

【蓝桥备赛】异或和——树状数组、DFS

题目链接 异或和 思路分析 树上每个点都有一个点权&#xff0c;对树上的更新操作是修改指定点的点权&#xff0c;查询操作是查询指定点为根结点的子树点权异或和。 这里的这些操作都和树状数组的单点修改和区间查询非常相似&#xff0c;即我们在修改一个点时&#xff0c;同时…

OpenCv —— cv::VideoCapture设置摄像头图像格式为“MJPEG“

背景 今天恰巧同事有台USB摄像头,她想要在Windows系统下通过OpenCV读取该摄像头宽高为1080x768、帧率为60的视频,用来做图像算法处理。但无奈通过网上OpenCV教程 读取的视频对应尺寸的帧率仅为10帧左右,根本无法满足使用要求。于是作者通过本篇文章介绍如何解决,欢迎交流指…

从0到1实现RPC | 04 负载均衡和静态注册中心

一、Router的定义 Router路由用于预筛选&#xff0c;Dubbo有这样的设计&#xff0c;SpringCloud没有。 二、LoadBanlancer定义 负载均衡器&#xff1a;默认取第一个 当前支持随机和轮询两种负载均衡器。 随机&#xff1a;从所有provider中随机选择一个。 轮询&#xff1a;每…

在 Jupyter Notebook 中轻松切换 Python 虚拟环境!

目录 1. 进入虚拟环境 2. 安装 ipykernel 3. 添加 kernel 4. 启动 Jupyter Notebook 5. 选择 kernel 1. 进入虚拟环境 进入cmd&#xff0c;输入conda activate myenv&#xff0c;myenv是虚拟环境名 2. 安装 ipykernel 确保虚拟环境中已安装了 ipykernel 包。如果没有&a…

【嵌入式硬件】三极管伏安特性曲线-饱和区

1.三极管伏安特性 三极管工作电路如下图所示。 三极管伏安特性曲线 书本上的描述: 截止区:三极管工作在截止状态,当发射结的电压Ube 小于 导通电压(0.6V-0.7V),发射结没有导通;集电结处于反向偏置,没有放大作用。 放大区:三极管的发射极加正向电压(…

Win10 下 Vision Mamba(Vim-main)的环境配置(libcuda.so文件无法找到,windows系统运行失败)

目录 1、下载NVIDIA 驱动程序、cuda11.8、cudnn8.6.0 2、在Anaconda中创建环境并激活 3、下载gpu版本的torch 4、配置环境所需要的包 5、安装causal_conv1d和mamba-1p1p1 安装causal_conv1d 安装mamba-1p1p1 6、运行main.py失败 请直接拉到最后查看运行失败的原因&am…

Linux+HA高可用24X7的安全保证

一&#xff0e; 介绍作为服务器&#xff0c;需要提供一定的24X7的安全保证&#xff0c;这样可以防止关键节点的宕机引起系统的全面崩溃。利用OpenSource开源软件&#xff0c;完成系统的高可靠双机热备方案。基于linux的 HA软件可靠稳定&#xff0c;比使用商业版本的HA软件降低成…

ubuntu-server部署hive-part3-安装mysql

参照 https://blog.csdn.net/qq_41946216/article/details/134345137 操作系统版本&#xff1a;ubuntu-server-22.04.3 虚拟机&#xff1a;virtualbox7.0 部署mysql 下载上传 下载地址 https://downloads.mysql.com/archives/community/ 以root用户上传&#xff0c;/usr/loc…

时序预测 | Matlab基于CFBP级联前向BP神经网络时序预测

时序预测 | Matlab基于CFBP级联前向BP神经网络时序预测 目录 时序预测 | Matlab基于CFBP级联前向BP神经网络时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab基于CFBP级联前向BP神经网络时序预测&#xff08;完整源码和数据)&#xff1b; 2.数据集为excel…

个人品牌打造IP孵化运营培训教程架构课件

【资料持续更新&#xff0c;以防走丢】 个人品牌打造IP孵化运营培训教程架构课件 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 个人品牌运营合集 &#xff08;完整资料包含以下内容&#xff09;目录 详细的个人IP运营方案&#xff1a; 1. 确定个人定位和…

Java基础——二、数据类型

二、数据类型 基本类型 类型说明 类型单位&#xff08;Byte&#xff09;取值范围byte1[128~127]short2[-32768~32767]int4[-2147483648~2147483647]char2[\u0000~\uFFFF]&#xff1a;注意加’ ’float4[3.402823e38 ~ 1.401298e-45]&#xff1a;e38表示是乘10的38次方double…

macbook(m1) ubuntu下载,复制粘贴和国内镜像源配置

ubuntu下载使用 官网下载Ubuntu 22.04.4 LTS (Jammy Jellyfish) Daily Build 打开后根据电脑的架构选择安装包&#xff0c;想要下载其他版本也可在官网中自行搜索。 我安装时舍友说他安装的是22.04这个版本&#xff0c;我也就跟着他安装了 注意&#xff1a;下载的版本最好有…