当前位置: 首页 > news >正文

归并排序及其应用

归并排序算法基于分而治之的概念,具体来说就是遍历一棵树,归并的过程是一个后序执行的动作。 由于我们知道每个子部分在合并后都是有序的,我们可以利用这个特性来解决一些问题。
归并排序图示
上图可视化了merge sort algorithm的过程,我们很容易看出树的深度是log(N)。 基本上我们必须在合并中对序列进行排序,时间复杂度是 O(N)。 所以这个算法的时间复杂度总共是Nlog(N)
根据上图的思路,我们可以很容易的编写出下面这个程序。

class Solution
{
public:vector<int> sortArray(vector<int> &nums){int len = nums.size();if (len < 2) return;int mid = len >> 1;vector<int> leftArray(nums.begin(), nums.begin() + mid);vector<int> rightArray(nums.begin() + mid, nums.end());sort(leftArray);sort(rightArray);mergeArray(nums, leftArray, rightArray);return nums;}void mergeArray(vector<int> &nums, vector<int> &leftArray, vector<int> &right){int leftSize = leftArray.size(), rightSize = rightArray.size();int cur = 0, cur1 = 0, cur2 = 0;while (cur1 < leftSize && cur2 < rightSize){if (leftArray[cur1] <= rightArray[cur2])nums[cur++] = leftArray[cur1++];elsenums[cur++] = rightArray[cur2++];}while (cur1 < leftSize)nums[cur++] = leftArray[cur1++];while (cur2 < rightSize)nums[cur++] = rightArray[cur2++];}
}

关于它的应用,我们总是试图找到一个问题是否可以应用合并后子部件有序的特性。 以下是应用“合并排序算法”的一些问题。
315. 计算右侧小于当前元素的个数
假设 i 指向左边的第一个元素,j 和 mid+1 指向右边的第一个元素。 当我们合并的时候,如果 temp[i] 小于 temp[j] ,我们可以知道有 j-mid-1 个元素小于 temp[i] ,因为数组是单调递增的。
合并示意
所以可以在合并的过程添加一些小小代码,其他的地方不变。

class Solution {
public:vector<pair<int, int>> temp;vector<int> count;vector<int> countSmaller(vector<int>& nums) {int n = nums.size();vector<pair<int, int>> num_index;for (int i = 0; i < n; i++)num_index.push_back(pair<int, int>(nums[i], i));temp = vector<pair<int, int>>(n);count = vector<int>(n, 0);merge_sort(num_index, 0, n-1);return count;}void merge_sort(vector<pair<int, int>>& num_index, int l, int r){if (l >= r) return;int mid = l + (r - l) / 2;merge_sort(num_index, l, mid);merge_sort(num_index, mid+1, r);merge(num_index, l, mid, r);}void merge(vector<pair<int, int>>& num_index, int l, int mid, int r){int i = l, j = mid + 1;int k = l;while (i <= mid && j <= r){if (num_index[i].first <= num_index[j].first){count[num_index[i].second] += j - mid - 1;temp[k++] = num_index[i++];}else temp[k++] = num_index[j++];}while (i <= mid) {count[num_index[i].second] += j - mid - 1; temp[k++] = num_index[i++];}while (j <= r) temp[k++] = num_index[j++];for (i = l; i <= r; i++)num_index[i] = temp[i];}
};

或者可以在后序位置操作一点点东西。
493. 翻转对
这个问题和上一个一样,只是有点不同。 我们假设下面有有序的左孩子和右孩子。 下一步是合并,但在此之前,我们可以计算左右之间的数字,betValue。 假设左边的数字是 leftValue,右边的数字是 rightValue。 可以递归计算最终结果。

class Solution
{
public:vector<int> tmp;int mergeSort(vector<int> &nums, int left, int right){if (left >= right)return 0;int mid = left + ((right - left) >> 1);int retLeft = mergeSort(nums, left, mid);int retRight = mergeSort(nums, mid + 1, right);int cur1 = left, cur2 = mid + 1;int ret = 0;while (cur1 <= mid){while (cur2 <= right && nums[cur1] / 2.0 > nums[cur2])cur2++;ret += cur2 - mid - 1;cur1++;}merge(nums, left, mid, right);return ret + retLeft + retRight;}void merge(vector<int> &nums, int left, int mid, int right){int cur1 = left, cur2 = mid + 1, cur = left;while (cur1 <= mid && cur2 <= right){if (nums[cur1] <= nums[cur2])tmp[cur++] = nums[cur1++];elsetmp[cur++] = nums[cur2++];}while (cur1 <= mid)tmp[cur++] = nums[cur1++];while (cur2 <= right)tmp[cur++] = nums[cur2++];for (int i = left; i <= right; i++)nums[i] = tmp[i];}int reversePairs(vector<int> &nums){int len = nums.size();tmp = vector<int>(len, 0);return mergeSort(nums, 0, len - 1);}
};

那么,如何获得betValue呢? 只需在后序空间添加一些代码。 我们可以得到右边第一个大于 nums[i] / 2.0 的元素。
327. 区间和的个数
是一样的,但是这里需要用到前缀和,理解为什么可以使用merge sort来解决这个问题。

class Solution
{
public:vector<long> tmp;int countRangeSum(vector<int> &nums, int lower, int upper){int len = nums.size();vector<long> preSum({0});for (int i = 0; i < len; i++)preSum.emplace_back(preSum[i] + nums[i]);tmp = vector<long>(preSum.size(), 0);return mergeSort(preSum, 0, preSum.size() - 1, lower, upper);}int mergeSort(vector<long> &nums, int left, int right, int lower, int upper){if (left >= right)return 0;int mid = left + ((right - left) >> 1);int retLeft = mergeSort(nums, left, mid, lower, upper);int retRight = mergeSort(nums, mid + 1, right, lower, upper);int cur1 = mid + 1, cur2 = mid + 1;int ret = 0;for (int i = left; i <= mid; i++){while (cur1 <= right && nums[cur1] - nums[i] < lower)cur1++;while (cur2 <= right && nums[cur2] - nums[i] <= upper)cur2++;ret += cur2 - cur1;}merge(nums, left, mid, right);return ret + retLeft + retRight;}void merge(vector<long> &nums, int left, int mid, int right){int cur1 = left, cur2 = mid + 1, cur = left;while (cur1 <= mid && cur2 <= right){if (nums[cur1] <= nums[cur2])tmp[cur++] = nums[cur1++];elsetmp[cur++] = nums[cur2++];}while (cur1 <= mid)tmp[cur++] = nums[cur1++];while (cur2 <= right)tmp[cur++] = nums[cur2++];for (int i = left; i <= right; i++)nums[i] = tmp[i];}
};

相关文章:

归并排序及其应用

归并排序算法基于分而治之的概念&#xff0c;具体来说就是遍历一棵树&#xff0c;归并的过程是一个后序执行的动作。 由于我们知道每个子部分在合并后都是有序的&#xff0c;我们可以利用这个特性来解决一些问题。 上图可视化了merge sort algorithm的过程&#xff0c;我们很容…...

【PAT甲级题解记录】1007 Maximum Subsequence Sum (25 分)

【PAT甲级题解记录】1007 Maximum Subsequence Sum (25 分) 前言 Problem&#xff1a;1007 Maximum Subsequence Sum (25 分) Tags&#xff1a;DP Difficulty&#xff1a;剧情模式 想流点汗 想流点血 死而无憾 Address&#xff1a;1007 Maximum Subsequence Sum (25 分) 问题描…...

华为OD机试真题Python实现【 最小叶子节点】真题+解题思路+代码(20222023)

最小叶子节点 题目 二叉树也可以用数组来存储, 给定一个数组,树的根节点的值储存在下标1, 对于储存在下标n的节点,他的左子节点和右子节点分别储存在下标2*n和2*n+1, 并且我们用-1代表一个节点为空, 给定一个数组存储的二叉树, 试求从根节点到最小的叶子节点的路径, …...

mars3d动态轨迹DynamicRoamLine,如何获取实时运⾏的经纬度

问题 1.期望 实现 实时显示经纬度、⾼度&#xff0c;做电⼦围栏报警判断 2.第⼀步就是要&#xff0c;获取实时运⾏的经纬度信息、⾼度信息&#xff0c;然后通过算法做电⼦围栏判断 3.使⽤了参数getOverPositions&#xff0c;发现返回的不是经纬度 相关链接 http://mars3d.cn//e…...

jvm常识

Jvm工作原理学习笔记0126一、JVM的生命周期1.JVM实例对应了一个独立运行的java程序它是进程级别a)启动。启动一个Java程序时&#xff0c;一个JVM实例就产生了&#xff0c;任何一个拥有public static void main(String[] args)函数的class都可以作为JVM实例运行的起点b)运行。ma…...

PHP部署、nginx与PHP的整合、PHP动态添加模块

文章目录前言一、基本知识1.php介绍2.PHP能做什么3.web工作原理4.PHP脚本主要用于领域5.php其他相关信息6.memcache介绍二、php的源码安装1.php安装2.php配置三、nginx与php整合四、php动态扩展模块&#xff08;memcache模块&#xff09;前言 一、基本知识 1.php介绍 官方下载…...

SpringCloud与SpringBoot的版本对应

一、SpringCloud与SpringBoot的版本对应 SpringCloud版本 SpringBoot版本 2021.0.1-SNAPSHOT Spring Boot >2.6.4-SNAPSHOT and <2.7.0-M1 2021.0.0 Spring Boot >2.6.1 and <2.6.4-SNAPSHOT 2021.0.0-RC1 Spring Boot >2.6.0-RC1 and <2.6.1 2021.0.0-M3 Sp…...

华为OD机试题,用 Java 解【N 进制减法】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…...

Linux->进程概念于基本创建

1. 进程基本概念 当一个可执行程序被加载到内存当中&#xff0c;并由操作系统将其管理起来&#xff0c;此时这个程序就被称之为进程。也就是下方的&#xff1a; 程序的一个执行实例&#xff0c;正在执行的程序等 担当分配系统资源&#xff08;CPU时间&#xff0c;内存&#xff…...

【MySQL】5.7版本解压安装配置

前言 之所以使用解压版本&#xff0c;而不使用exe安装&#xff0c;因为exe的安装方式删除过于麻烦&#xff01;&#xff01;&#xff01; 如果安装MySQL过程中&#xff0c;出错了或者想重新在来一把&#xff0c;删除mysql服务即可 sc delete mysql # 删除已经安装好的Mysql&a…...

c++类对象数据成员和虚函数的内存布局

一直想搞清楚类对象的数据成员和虚函数的内存布局&#xff0c;今天刚好有时间&#xff0c;所以就写了个demo查看了一下具体的内存布局情况&#xff08;使用的编译器为微软的&#xff09;。下面是自己demo的代码&#xff1a;#include <iostream> #include <windows.h&g…...

Python 模块和包

1. 模块和包 **容器&#xff1a;**列表、元组、字符串、字典等&#xff0c;对数据的封装**函数&#xff1a;**对语句的封装**类&#xff1a;**对方法和属性的封装&#xff0c;即对函数和数据的封装 而模块&#xff08;module&#xff09;就是个程序&#xff0c;一个.py 文件&…...

Java零基础专栏——面向对象

1 面向对象思想1.1 什么是面向对象&#xff1f;2 类和对象2.1 类和对象的理解2.2 类的定义2.3定义类的补充注意事项2.4 对象的使用2.5 练习3 封装3.1 封装思想3.1.1 封装概述3.1.2 封装的步骤3.1.3 封装代码实现3.2 private关键字3.3 练习—private的使用4 构造方法4.1 构造方法…...

离散无记忆与有记忆信源的序列熵

本专栏包含信息论与编码的核心知识&#xff0c;按知识点组织&#xff0c;可作为教学或学习的参考。markdown版本已归档至【Github仓库&#xff1a;information-theory】&#xff0c;需要的朋友们自取。或者公众号【AIShareLab】回复 信息论 也可获取。 文章目录离散无记忆信源的…...

算法该不该刷?如何高效刷算法?

一、算法该不该刷&#xff1f;最近有小伙伴向我咨询一个问题&#xff0c;就是算法该不该刷&#xff0c;该如何刷算法呢&#xff1f;这个问题可谓太大众化了&#xff0c;只要你去某乎、某度搜索一下相关的解答&#xff0c;会有无数种回答&#xff0c;可见这个问题困扰了多少学习…...

Allegro如何在关闭飞线模式下查看网络连接位置操作指导

Allegro如何在关闭飞线模式下查看网络连接位置操作指导 在用Allegro做PCB设计的时候,有时会因为设计需要,关闭飞线显示。 如何在关闭飞线显示模式下查看网络连接的位置,如下图 除了能看到网络连接的点位以外,还能看到器件的pin Number 如何显示出这种效果,具体操作如下 …...

啊哈 算法读书笔记 第 1 章 一大波数正在靠近——排序

目录 排序算法&#xff1a; 时间复杂度&#xff1a; 排序算法和冒泡排序之间的过渡&#xff1a; 冒泡排序 冒泡排序和快速排序之间的过渡&#xff1a; 快速排序 排序算法&#xff1a; 首先出场的是我们的主人公小哼&#xff0c;上面这个可爱的娃就是啦。期末考试完了老…...

Servlet笔记(5):HTTP请求与响应

1、HTTP请求 当浏览器请求网页时&#xff0c;它会向Web服务器发送特定信息&#xff0c;这些信息不能被直接读取&#xff0c;而是通过传输HTTP请求时&#xff0c;封装进请求头中。 有哪些头信息&#xff1f; 头信息描述Accept这个头信息指定浏览器或其他客户端可以处理的 MIME…...

信号的运算与变换

目录 前言 本章内容介绍 信号的运算与变换 相加 相乘 时移 反折 尺度变换 微分&#xff08;差分&#xff09; 积分&#xff08;累加&#xff09; 信号的奇偶求解 信号的实虚分解 合适的例题 1、时移反折 2、时移尺度 3、时移反折尺度 4、反求x(t) 前言 《信号…...

【GO】K8s 管理系统项目9[API部分--Secret]

K8s 管理系统项目[API部分–Secret] 1. 接口实现 service/dataselector.go // secret type secretCell corev1.Secretfunc (s secretCell) GetCreation() time.Time {return s.CreationTimestamp.Time }func (s secretCell) GetName() string {return s.Name }2. Secret功能…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

webpack面试题

面试题&#xff1a;webpack介绍和简单使用 一、webpack&#xff08;模块化打包工具&#xff09;1. webpack是把项目当作一个整体&#xff0c;通过给定的一个主文件&#xff0c;webpack将从这个主文件开始找到你项目当中的所有依赖文件&#xff0c;使用loaders来处理它们&#x…...

写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里

写一个shell脚本&#xff0c;把局域网内&#xff0c;把能ping通的IP和不能ping通的IP分类&#xff0c;并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...