【优选算法】D&C-Mergesort-Harmonies:分治-归并的算法之谐

【优选算法】D&C-Mergesort-Harmonies:分治-归并的算法之谐

文章目录

本篇是优选算法之分治-归并,简单来说就是一个不断分组排序再合并的过程

1.概念解析

🚩什么是分治-归并?

分治归并(基于分治思想的归并排序)是分治算法(Divide and Conquer)在排序问题中的经典应用,核心是通过 “拆分 - 排序 - 合并” 三步,将无序数组转化为有序数组,本质是 “化繁为简、再合简为繁” 的解题思路

2.排序数组

✏️题目描述:

在这里插入图片描述

✏️示例:

在这里插入图片描述
传送门:排序数组

题解:

在这里插入图片描述

本质上分治归并就是一个后序遍历,而快排就是一个前序遍历,不断向下细分数组,然后从下往上把左右两分支的数组排序并合并,以此向上循环往复

💻细节问题:

  • int mid = left + ((right - left) >> 1) 相当于 int mid = left + ((right - left) / 2),二进制的算法效率更高,且该计算中间值的方法能避免整数溢出
  • 最后一步合并数组,nums[left + j] = tmp[j] 而不是 nums[j] = tmp[j],是因为 left 不一定是 0,即不一定是对原来的整个数组进行排序,可能只对数组一部分进行排序
  • 数组排序并不影响逆序对的计算,因为是左右两部分比较,内部已经在递归过程中计算过了

💻代码实现:

#include<iostream>#include<vector>usingnamespace std;classSolution{ vector<int> tmp;public: vector<int>sortArray(vector<int>& nums){ tmp.resize(nums.size());mergeSort(nums,0, nums.size()-1);return nums;}voidmergeSort(vector<int>& nums,int left,int right){if(left >= right){return;}int mid = left +((right - left)>>1);mergeSort(nums, left, mid);mergeSort(nums, mid +1, right);int cur1 = left, cur2 = mid +1, i =0;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 j =0; j <= right - left;++j){ nums[left + j]= tmp[j];}}};

3.交易逆序对的总数

✏️题目描述:

在这里插入图片描述

✏️示例:

在这里插入图片描述
传送门:交易逆序对的总数

题解:

在这里插入图片描述

因为归并排序的 “分治 + 有序合并” 特性,完美匹配逆序对统计的核心需求 —— 高效拆分问题、批量计算逆序对,这是暴力枚举做不到的,当 [left,mid][mid+1,right] 进行互相比较时,如果是升序,获取到 record[cur1] >= record[cur2] 时,由于是有序,所以 cur2 往后都是小于 cur1 对应的数的,所以能直接得到很多对逆序数。用降序也是同理

💻代码实现:

classSolution{ vector<int> tmp;public:intreversePairs(vector<int>& record){ tmp.resize(50010);returnmergeSort(record,0, record.size()-1);}intmergeSort(vector<int>&record,int left,int right){if(left >= right){return0;}int ret =0;int mid = left +((right - left)>>1); 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 j =0; j < right - left +1;++j){ record[j + left]= tmp[j];}return ret;}};

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

✏️题目描述:

在这里插入图片描述

✏️示例:

在这里插入图片描述
传送门:计算右侧小于当前元素的个数

题解:

在这里插入图片描述


这题和上一题思路基本一致,唯一的难点就是要额外创建一个数组进行值和下表的绑定,因为题目要求的是返回每个 index 对应的值,有人就问了为什么不能用哈希表,可以是可以但是有重复值的话会很麻烦,因此额外创建一个数组进行 index 和值的绑定更方便,index 数组跟着 nums 数组移动就行

💻代码实现:

classSolution{ vector<int> ret; vector<int> index;int tmpNums[500010];int tmpindex[500010];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;}voidmergeSort(vector<int>& nums,int left,int right){if(left >= right){return;}int mid = left +((right - left)>>1);mergeSort(nums, left, mid);mergeSort(nums, mid +1, right);int cur1 = left, cur2 = mid +1, i =0;while(cur1 <= mid && cur2 <= right){if(nums[cur1]<= nums[cur2]){ tmpNums[i]= nums[cur2]; tmpindex[i++]= index[cur2++];}else{ ret[index[cur1]]+= right - cur2 +1; tmpNums[i]= nums[cur1]; tmpindex[i++]= index[cur1++];}}while(cur1 <= mid){ tmpNums[i]= nums[cur1]; tmpindex[i++]= index[cur1++];}while(cur2 <= right){ tmpNums[i]= nums[cur2]; tmpindex[i++]= index[cur2++];}for(int j =0; j < right - left +1;++j){ nums[j + left]= tmpNums[j]; index[j + left]= tmpindex[j];}}};

5.翻转对

✏️题目描述:

在这里插入图片描述

✏️示例:

在这里插入图片描述
传送门:翻转对

题解:

在这里插入图片描述

思路还是利用归并解决,但是要提前计算符合题目要求的翻转对,如果在排序过程中进行计算,会漏掉部分翻转对

💻细节问题:

(long long)nums[cur1] <= 2 * (long long)nums[cur2] 防止溢出

💻代码实现:

classSolution{ vector<int> tmp;int ret =0;public:intreversePairs(vector<int>& nums){ tmp.resize(nums.size());mergeSort(nums,0, nums.size()-1);return ret;}voidmergeSort(vector<int>& nums,int left,int right){if(left >= right){return;}int mid = left +((right - left)>>1);mergeSort(nums, left, mid);zq mergeSort(nums, mid +1, right);int cur1 = left, cur2 = mid +1, i =0;while(cur2 <= right){while(cur1 <= mid &&(longlong)nums[cur1]<=2*(longlong)nums[cur2]){ cur1++;}if(cur1 > mid){break;} ret += mid - cur1 +1; cur2++;} cur1 = left, cur2 = mid +1;while(cur1 <= mid && cur2 <= right){if(nums[cur1]<= nums[cur2]){ tmp[i++]= nums[cur1++];}else{ tmp[i++]= nums[cur2++];}}while(cur1 <= mid){ tmp[i++]= nums[cur1++];}while(cur2 <= right){ tmp[i++]= nums[cur2++];}for(int j =0; j < right - left +1;++j){ nums[j + left]= tmp[j];}}};

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

请添加图片描述

Read more

Python CAD数据处理实战指南:从DXF文件解析到3D建模全流程

Python CAD数据处理实战指南:从DXF文件解析到3D建模全流程 【免费下载链接】ezdxfPython interface to DXF 项目地址: https://gitcode.com/gh_mirrors/ez/ezdxf 在当今数字化设计时代,CAD数据处理已成为工程设计和制造业的核心环节。Python凭借其强大的数据处理能力和丰富的生态系统,为CAD文件处理提供了理想的解决方案。特别是ezdxf库,作为一个专业的Python DXF处理工具,能够帮助开发者轻松应对从基础几何创建到复杂3D模型生成的各类挑战。 🎯 为什么选择Python进行CAD数据处理? 传统CAD软件虽然功能强大,但在批量处理、自动化流程和集成开发方面存在诸多限制。Python的介入正好弥补了这些不足: 核心优势对比: | 传统CAD软件 | Python + ezdxf | |------------|-------------| | 手动操作,效率有限 | 自动化批量处理 | | 封闭系统,集成困难 | 开放生态,易于集成 | | 学习成本高,操作复杂 | 代码驱动,逻辑清晰 |

By Ne0inhk
(Python)Python爬虫入门教程:从零开始学习网页抓取(爬虫教学)(Python教学)

(Python)Python爬虫入门教程:从零开始学习网页抓取(爬虫教学)(Python教学)

一、爬虫基础概念 什么是爬虫? 网络爬虫(Web Crawler)是一种自动获取网页内容的程序,它像蜘蛛一样在互联网上"爬行",收集和提取数据。 爬虫应用场景: 1. 搜索引擎(Google、百度) 2. 价格监控(电商比价) 3. 舆情分析(社交媒体监控) 4. 数据采集(研究、分析) 二、环境准备 1. 安装Python * 官网下载:Download Python | Python.org * 安装时勾选"Add Python to PATH" 2. 安装必要库(命令行执行) pip install requests beautifulsoup4

By Ne0inhk

YOLOv9摄像头实时检测,python detect_dual.py命令详解

YOLOv9摄像头实时检测,python detect_dual.py命令详解 在当前智能视觉应用快速发展的背景下,YOLOv9凭借其卓越的精度与推理效率,成为目标检测领域的新标杆。本镜像基于官方代码库构建,预装完整深度学习环境,支持开箱即用的训练、推理与评估流程。本文将重点解析如何使用python detect_dual.py实现摄像头实时检测,并深入剖析该命令的核心参数配置、运行逻辑及工程实践要点。 1. 环境准备与基础调用 1.1 镜像环境初始化 本镜像已集成以下关键组件: * PyTorch 1.10.0 + CUDA 12.1:保障高性能GPU推理 * OpenCV-Python:用于视频流采集与图像处理 * YOLOv9官方代码库:位于 /root/yolov9 * 预置权重文件 yolov9-s.pt:无需额外下载即可启动推理 启动容器后,首先激活专用conda环境: conda activate yolov9 cd /root/yolov9

By Ne0inhk
基于Python的量化交易实盘部署与风险管理指南

基于Python的量化交易实盘部署与风险管理指南

基于Python的量化交易实盘部署与风险管理指南 一、模拟交易与参数优化 1.1 券商API接入与模拟交易 在量化交易落地前,模拟交易是策略验证的“安全沙箱”,其核心价值在于用零成本环境暴露策略缺陷。以股票市场为例,同花顺与通达信模拟盘接口覆盖A股全品种行情与交易功能,但接口特性存在显著差异: * 同花顺采用HTTP轮询获取行情,适合低频策略测试,认证流程需通过MD5加密密码与时间戳生成签名,确保请求合法性; * 通达信提供WebSocket实时行情推送,延迟低至50ms,适合高频策略验证,需通过IP白名单+Token双重认证。 代码示例中,auth_ths函数演示了同花顺的签名算法,而WebSocket连接实现了实时行情的无阻塞接收,为策略实时计算提供数据源。 数字货币领域,Binance Testnet是最佳实践平台,其与主网完全一致的API接口支持现货、杠杆、永续合约全场景模拟。通过base_url参数切换至测试网,配合CCXT库统一多交易所接口,可实现策略的跨平台迁移测试。示例中市价单下单逻辑需注意:测试网的USDT通常为虚拟资产,需提前通过Faucet获

By Ne0inhk