当前位置: 首页 > 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功能…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...