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

算法分析—— 《归并排序》

《排序数组》

题目描述:

给你一个整数数组 nums,请你将该数组升序排列。

你必须在 不使用任何内置函数 的情况下解决问题,时间复杂度为 O(nlog(n)),并且空间复杂度尽可能小。

示例 1:

输入:nums = [5,2,3,1]
输出:[1,2,3,5]

示例 2:

输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]

代码实现:

class Solution 
{
public:vector<int> tmp;vector<int> sortArray(vector<int>& nums) {tmp.resize(nums.size());MergeSort(nums, 0, nums.size() - 1);return nums;}void MergeSort(vector<int>& nums, int l, int r){if(l >= r) return;int mid = (r + l) >> 1;MergeSort(nums, l, mid);MergeSort(nums, mid + 1, r);int cur1 = l, cur2 = mid + 1, i = 0;while(cur1 <= mid && cur2 <= r) tmp[i++] = nums[cur1] >= nums[cur2] ? nums[cur2++] : nums[cur1++];while(cur1 <= mid) tmp[i++] = nums[cur1++];while(cur2 <= r) tmp[i++] = nums[cur2++];for(int i = l; i <= r; ++i) nums[i] = tmp[i - l];}
};

代码解析:

对于同一种排序题目来说,不仅仅要去掌握快速排序,接触其他的排序新思路也尤为重要,不管是归并排序还是快速排序,其本质的思路就是两个字 —— 分治。

所以归并排序是最简单的,利用递归的思路,我们就认为这个递归操作一定可以做到,那么最终就是实现一个「合并两个有序数组」的操作。

那这个操作很简单,利用双指针就可以非常轻松的实现了,在这里我就不过多赘述,因为确实不难。

《交易逆序对的总数》

题目描述:

在股票交易中,如果前一天的股价高于后一天的股价,则可以认为存在一个「交易逆序对」。请设计一个程序,输入一段时间内的股票交易记录 record,返回其中存在的「交易逆序对」总数。

示例 1:

输入:record = [9, 7, 5, 4, 6]
输出:8
解释:交易中的逆序对为 (9, 7), (9, 5), (9, 4), (9, 6), (7, 5), (7, 4), (7, 6), (5, 4)。

代码实现:

class Solution 
{
public:vector<int> tmp;int reversePairs(vector<int>& record) {tmp.resize(record.size());return mergesort(record, 0, record.size() - 1);}int mergesort(vector<int>& record, int left, int right){if(left >= right) return 0;int mid = (left + right) >> 1;int ret = 0;ret += mergesort(record, left, mid);ret += mergesort(record, mid + 1, right);int cur1 = left, cur2 = mid + 1, i = 0;while(cur1 <= mid && cur2 <= right){if(record[cur1] <= record[cur2]) tmp[i++] = record[cur1++];else {ret += (mid - cur1 + 1);tmp[i++] = record[cur2++];} }while(cur1 <= mid) tmp[i++] = record[cur1++];while(cur2 <= right) tmp[i++] = record[cur2++];for(int i = left; i <= right; ++i){record[i] = tmp[i - left];}return ret;}};

代码解析:

题目意思很好理解,就是定一个数字,然后去后面找有没有比这个数小的,记住一定是要去后面找。

最简单的解法就是利用双指针套两层for循环直接暴力解决,但是最终会超时,这就很尴尬。

第二个方法,就是利用分治归并的思路来解决题目。

我们最主要的研究可以转换成「找出该数前,有多少个数比我大」

那现在假设我们利用了「归并」将数组排好了升序了,但是还没有「合并两个有序数组」,大致的情况如下:

因为这个判断也需要指针移动,所以我们就可以在排序的过程中,就将答案给算出来。

因为单调性,所以在nums[cur1] > nums[cur2]的情况下,cur1后面的数都大于nums[cur2]

《计算右侧小于当前元素的个数》

题目描述:

给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。

示例 1:

输入:nums = [5,2,6,1]
输出:[2,1,1,0] 
解释:
5 的右侧有 2 个更小的元素 (2 和 1)
2 的右侧仅有 1 个更小的元素 (1)
6 的右侧有 1 个更小的元素 (1)
1 的右侧有 0 个更小的元素

示例 2:

输入:nums = [-1]
输出:[0]

示例 3:

输入:nums = [-1,-1]
输出:[0,0]

代码实现:

class Solution 
{
public:vector<pair<int, int>> tmp;     // 追踪numsvector<int> ret;                // 接受答案vector<pair<int, int>> assist;  // 哈希绑定(原数据 + 下标)vector<int> countSmaller(vector<int> &nums){for (int i = 0; i < nums.size(); ++i){assist.push_back(make_pair(nums[i], i));}ret.resize(nums.size());tmp.resize(assist.size());Mergesort(assist, 0, nums.size() - 1);return ret;}void Mergesort(vector<pair<int, int>> &assist, int left, int right){if (left >= right) return;int mid = (right + left) >> 1;Mergesort(assist, left, mid);Mergesort(assist, mid + 1, right);int cur1 = left, cur2 = mid + 1, i = 0;while (cur1 <= mid && cur2 <= right){if (assist[cur1].first <= assist[cur2].first) tmp[i++] = assist[cur2++];else{ret[assist[cur1].second] += right - cur2 + 1;tmp[i++] = assist[cur1++];}}while (cur1 <= mid) tmp[i++] = assist[cur1++];while (cur2 <= right) tmp[i++] = assist[cur2++];for (int i = left; i <= right; ++i) assist[i] = tmp[i - left];}};

代码解析:

这道题目总体来说,与上一道题的算法思路一样,上一道题是记录有多少个前面大于后面的数字,而这道题是将每个坐标的数字统计起来,然后将确切的数据按照下标统计。

所以使用归并排序,我们无法固定住下标,因为下标会随着排序而发生变化。所以这正是我们需要去解决的。

一开始我考虑使用哈希表,但是数组可能会出现重复数据,所以哈希表pass了,但是我们可以仍然采用哈希的算法思路,将数据和下标绑定在一起。那么这时候我们可以使用vector<pair<int, int>>来模拟哈希表。

拿题目自带的例子:

这样子在排序改变数据位置的同时,下标也随之改变了。

然后也是基于上一道题了,不过这里我们不应该排「升序」,而是排「降序」,因为我们是要找右侧有多少个元素比自己小,那竟然如此我们可以画个图理解理解。

因为单调性,所以nums[cur1]大于cur2后面的全部数。

剩下的思路也是一样的,只是需要注意pair的first和seconde的取值。

《翻转对》

题目描述:

给定一个数组 nums ,如果 i < jnums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对****。

你需要返回给定数组中的重要翻转对的数量。

示例 1:

输入: [1,3,2,3,1]
输出: 2

示例 2:

输入: [2,4,3,5,1]
输出: 3

注意:

  1. 给定数组的长度不会超过50000
  2. 输入数组中的所有数字都在32位整数的表示范围内。

代码实现:

class Solution 
{
public:vector<int> tmp;int reversePairs(vector<int>& nums) {tmp.resize(nums.size());return MergeSort(nums, 0, nums.size() - 1);}int MergeSort(vector<int>& nums, int left, int right){if(left >= right) return 0;int mid = (left + right) >> 1;int ret = 0;ret += MergeSort(nums, left, mid);ret += MergeSort(nums, mid + 1, right);int cur1 = left, cur2 = mid + 1, i = 0;while(cur1 <= mid){while(cur2 <= right && nums[cur1] / 2.0 <= nums[cur2]) ++cur2;if(cur2 > right) break;ret += (right - cur2 + 1);++cur1;}cur1 = left, cur2 = mid + 1;while(cur1 <= mid && cur2 <= right)tmp[i++] = nums[cur1] > nums[cur2] ? nums[cur1++] : nums[cur2++];while(cur1 <= mid) tmp[i++] = nums[cur1++];while(cur2 <= right) tmp[i++] = nums[cur2++];for(int i = left; i <= right; ++i) nums[i] = tmp[i - left];return ret;}};

代码解析:

一样,这道题和前面的内容算法一样,只不过这里是判断是否大于2倍。

那在这里我们在实现「合并两个有序数组」之前,就可以先通过双指针进行一次判断,再去排序,因为你无法控制是以2倍为标准然后向右移动还是统计数据,而且经过排序后,数据也会乱了,因此我们必须在排序之前就通过双指针做好统计。

相关文章:

算法分析—— 《归并排序》

《排序数组》 题目描述&#xff1a; 给你一个整数数组 nums&#xff0c;请你将该数组升序排列。 你必须在 不使用任何内置函数 的情况下解决问题&#xff0c;时间复杂度为 O(nlog(n))&#xff0c;并且空间复杂度尽可能小。 示例 1&#xff1a; 输入&#xff1a;nums [5,2…...

SpringBoot启动时报错:cannot use an unresolved DNS server address: I:53

报错如下&#xff1a; 2025-02-17 13:59:41.374 [main] ERROR org.springframework.boot.SpringApplication:835 - Application run failed org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name mySwaggerResourceProvider def…...

AI进展不止于基准:深度解析Grok 3的局限

基准测试长期以来一直是AI评估的基石,但任何认真的AI科学家都知道它们是可以被“游戏化”的。 我曾经详细写过这个问题,甚至LMsys也不得不调整其盲测格式——将Grok 3用不同的标签代替,而不仅仅是隐藏品牌——以减少品牌偏见。 高能力AI,尤其是像GPT-4级别的模型,或那些依…...

物联网技术赋能预测性维护的深度剖析与前景展望

一、引言 1.1 研究背景与意义 随着信息技术的飞速发展,物联网技术已逐渐渗透到各个行业领域,成为推动产业变革和创新的重要力量。物联网通过将各种设备、物品与互联网连接,实现数据的采集、传输和交互,为各行业带来了前所未有的智能化和自动化水平提升。在工业领域,设备…...

Python变量作用域250218

函数调用时&#xff0c;会创建自己的独有的作用域作用域是以函数为作用域的而且使用条件语句&#xff0c;可能让定义一些变量的代码运行&#xff0c;从而创建其内部变量&#xff0c;如果定义条件不成立&#xff0c;这些变量就不会被创建并被使用变量只要在函数中出现&#xff0…...

SQL Server 运算符优先级

在 SQL Server 中&#xff0c;运算符的优先级决定了在没有使用括号明确指定计算顺序时&#xff0c;运算符的执行顺序。 运算符优先级列表 括号 () 一元运算符 &#xff08;正号&#xff09;-&#xff08;负号&#xff09;~&#xff08;按位取反&#xff09; 乘法、除法和取模…...

Miniconda + VSCode 的Python环境搭建

目录&#xff1a; 安装 VScode 安装 miniconda 在VScode 使用conda虚拟环境 运行Python程序 1.安装 vscode 编辑器 官网链接&#xff1a;Visual Studio Code - Code Editing. Redefined 下载得到&#xff1a;&#xff0c;双击安装。 安装成功…...

AI提示词进阶:RTGO与CO-STAR框架实战指南

掌握提示词设计是解锁AI生产力的关键。本文将深入解析两大顶尖框架RTGO与CO-STAR&#xff0c;通过程序员视角拆解技术原理&#xff0c;配合真实案例演示如何根据场景精准选型。 一、框架定位与技术特性对比 维度RTGO框架CO-STAR框架架构四层递进式结构六维网状结构响应速度0.8…...

【python】4_异常

目录 一、异常处理 1、异常捕获 基本捕获语法&#xff1a; 捕获指定异常&#xff1a; 捕获多个异常&#xff1a; 捕获所有异常&#xff1a; 异常else & finally&#xff1a; 2、异常的传递性 二、模块 模块的导入方式 1、语法 2、as 定义别名 一、异常处理 1、异常…...

Python Spider

Python Spider&#xff0c;即Python爬虫&#xff0c;是一种使用Python编程语言编写的自动化程序&#xff0c;用于从互联网上抓取数据。这些程序通常模拟人类用户的网络行为&#xff0c;如访问网页、提交表单、点击链接等&#xff0c;以收集所需的信息。Python爬虫广泛应用于数据…...

防御保护选路练习

拓扑 配置 IP的基本配置 r2 [R2]int g0/0/0 [R2-GigabitEthernet0/0/0]ip add 12.0.0.2 255.255.255.0 [R2]int g0/0/2 [R2-GigabitEthernet0/0/2]ip add 210.1.1.254 255.255.255.0 [R2-GigabitEthernet0/0/2]int g0/0/1 [R2-GigabitEthernet0/0/1]ip add 200.1.1.254 255.…...

AI性能极致体验:通过阿里云平台高效调用满血版DeepSeek-R1模型

前言 解决方案链接&#xff1a; https://www.aliyun.com/solution/tech-solution/deepseek-r1-for-platforms?utm_contentg_1000401616 DeepSeek是近期爆火的开源大语言模型&#xff08;LLM&#xff09;&#xff0c;凭借其强大的模型训练和推理能力&#xff0c;受到越来越多…...

Windows本地部署DeepSeek

文章目录 一、准备工作1、准备服务器2、准备APP 二、部署deepseek-r11、脚本部署2、脚本部署 三、ChatBox集成 一、准备工作 1、准备服务器 本案例使用Windows电脑 2、准备APP Download Ollama Download Chatbox 二、部署deepseek-r1 1、脚本部署 双击安装完Ollama,默认…...

力扣高频sql 50题(基础版) :NULL, 表连接,子查询,case when和avg的结合

NULL的处理 nvl(字段,num) 和数字进行比较需要先使用nvl(字段,num)函数处理空值 思路: 没有被id 2 的客户推荐>> 过滤条件 referee_id !2 没有被id 2 的客户推荐>>被其他客户推荐, 但是也有可能没有被任何客户推荐>>NULL 考点: NULL是 不一个具体的数…...

通俗理解-L、-rpath和-rpath-link编译链接动态库

一、参考资料 链接选项 rpath 的应用和原理 | BewareMyPower的博客 使用 rpath 和 rpath-link 确保 samba-util 库正确链接-CSDN博客 编译参数-Wl和rpath的理解_-wl,-rpath-CSDN博客 Using LD, the GNU linker - Options Directory Options (Using the GNU Compiler Colle…...

【Python】02-Python简介

文章目录 1、计算机语言简介2、编译型语言和解释性语言3、Python简介3.1 简介3.2 用途 4、开发环境搭建5、交互界面6、Sublime和Python整合 1、计算机语言简介 计算机语言 定义&#xff1a;人类与计算机之间进行信息交流的工具&#xff0c;它通过特定的符号、语法规则和语义结构…...

C++中变量与容器的默认初始化:0的奥秘

在C编程的世界里&#xff0c;初始化是一个至关重要的概念。它决定了变量或容器在程序开始执行时的初始状态。然而&#xff0c;对于不同的数据类型和容器&#xff0c;C标准对于默认初始化的行为有着不同的规定。本文将深入探讨C中变量与容器的默认初始化规则&#xff0c;特别是关…...

C#中File.Copy方法的参数overwrite取false和true的区别

当调用 System.IO.File.Copy 方法时&#xff0c;第三个参数 overwrite 控制着如果目标位置已经存在同名文件的情况下如何处理。 1、当 overwrite 设置为 true 在这种情况下&#xff0c;即使目标路径下已经有相同名称的文件&#xff0c;该方法也会无条件地覆盖现有的文件。这不…...

用promptfoo做大模型安全性测评

1. 引入 promptfoo 是一款专为大模型安全测试打造的强大工具。它能通过红队测试、渗透测试以及漏洞扫描等方式&#xff0c;对各类大模型展开深度安全评估&#xff0c;全面检测模型在不同场景下的安全性。 2. 运行promptfoo的过程 安装nodejs 用npm安装promptfoo npm insta…...

软件评测师复习之计算机网络(4)

目录 (一)1.网络功能和分类2.OSI七层模型3.TCP/IP协议4.传输介质(二)1.通信方式和交换方式2.IP地址3.IPv64.网络规划与设计5.磁盘冗余阵列6.网络存储技术(一) 1.网络功能和分类 计算机网络功能:数据通信、资源共享、负载均衡、高可靠性 按分布范围和拓扑结构划分: 网络分类…...

用STC-ISP写延时函数

若想写出自己可以定义时长的延时函数&#xff0c;需要重新生成一个1ms的延时函数并稍加修改。 STC-ISP生成的1ms的延时函数代码如下&#xff1a; void Delay1ms(void) //12.000MHz {unsigned char data i, j;i 2;j 239;do{while (--j);} while (--i); }将上述代码改为可自定…...

Jetson Agx Orin平台JP6.0-r36.3版本修复了vi模式下的原始图像损坏(线条伪影)

1.问题描述 这是JP-6.0 GA/ l4t-r36.3.0的一个已知问题 通过vi模式捕获的图像会导致异常线条 参考下面的快照来演示这些线伪影 这个问题只能通过VI模式进行修复,不应该通过LibArgus看到。 此外,这是由于内存问题。 由于upstream已经将属性名称更改为“dma-noncoherent”…...

MSI微星电脑冲锋坦克Pro Vector GP76 12UGS(MS-17K4)原厂Win11系统恢复镜像,含还原功能,预装OEM系统下载

适用机型&#xff1a;【MS-17K4】 链接&#xff1a;https://pan.baidu.com/s/1P8ZgXc6S_J9DI8RToRd0dQ?pwdqrf1 提取码&#xff1a;qrf1 微星笔记本原装出厂WINDOWS11系统自带所有驱动、出厂主题壁纸、系统属性专属联机支持标志、Office办公软件、MSI Center控制中心等预装…...

Pycharm中断点使用技巧

1. 打开项目并准备代码 首先&#xff0c;打开 PyCharm 并加载你的 Python 项目&#xff0c;确保你已经有想要调试的 Python 代码文件。如&#xff1a; def add_numbers(a, b):result a breturn resultnum1 5 num2 3 sum_result add_numbers(num1, num2) print(f"Th…...

PageHelper分页插件

文章目录 1、使用方式2、原理3、注意事项 1、使用方式 引入 PageHelper 插件 <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.11</version> </dependency>在 mybat…...

洛谷P11042 [蓝桥杯 2024 省 Java B] 类斐波那契循环数

像是这种填空题的话&#xff0c;就直接暴力还更加省时间&#xff0c;在本地算完后直接提交答案即可 #include<bits/stdc.h> using namespace std;const int N 10000000;bool isnumber(int n) {vector<int> a;int m n;while (n > 0) {a.push_back(n % 10);n / …...

echarts心电图封装方法

效果图 代码 <div id"line1" style"width: 100%;height: 100px;"></div>// 生成图标方法 /*** 生成图表* param {array} cData 图表数据* param {string} home 图表渲染位置Id* param {number} speed 刷新速度 值越大&#xff0c;刷新速度越快…...

使用Linux创作第一个小程序--进度条

Linux第一个小程序 - 进度条 储备知识 1.回车换行 回车概念 \r 换行概念 \n 2.缓冲区 sleep 先执行1 后执行2&#xff08;c语言中是按顺序执行的&#xff09; 那么在我sleep期间&#xff0c;“Hello World”一定是被保存起来了&#xff08;缓冲区&#xff09;。 缓冲区&a…...

初识LLMs

目录 一、Language AI 历史 二、Language AI如何处理text 三、技术一&#xff1a;Bag-of-Words模型 缺点 四、技术二&#xff1a;word2vec&#xff08;稠密向量 / 嵌入向量&#xff09; 缺点 五、嵌入的多种形式 六、技术三&#xff1a;注意力机制 6.1 上下文嵌入 缺…...

SpringAI系列 - RAG篇(三) - ETL

目录 一、引言二、组件说明三、集成示例一、引言 接下来我们介绍ETL框架,该框架对应我们之前提到的阶段1:ETL,主要负责知识的提取和管理。ETL 框架是检索增强生成(RAG)数据处理的核心,其将原始数据源转换为结构化向量并进行存储,确保数据以最佳格式供 AI 模型检索。 …...