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

027.归并排序

归并排序就是二叉树后序遍历

二叉树后序遍历

  • 先遍历左右子树,再处理根节点

  • 可以获取左右子树的信息

void postorder(TreeNode*root){if(root==nullptr){return;}//先处理左右子树postorder(root->left);postorder(root->right);//后序位置
}

归并排序

  • 区间一分为二,先排序左右区间,再归并

  • 得到左右两个有序子区间

void mergesort(vector<int>&nums,int left,int right){//只有一个元素,本身就是有序的if(left==right){return;}vector<int>temp;int mid=left+(right-left)>>1;//先排序左右区间mergesort(nums,left,mid);mergesort(nums,mid+1,right);//得到两个有序子区间//归并int i=left,j=mid+1;while(i<=mid&&j<=right){if(nums[i]<nums[j]){temp.push_back(nums[i++]);}else temp.push_back(nums[j++]);}while(i<=mid){temp.push_back(nums[i++]);}while(j<=right){temp.push_back(nums[j++]);} for(int x:temp){nums[left++]=x;}
}

应用 :不止排序

如果只是为了排序我们有很多平替,一般没人特意写个归并排序出来, std::sort() 不香吗

归并排序的特殊之处在于它在排序的过程中可以得到两个有序子区间

我们往往在归并这一过程中对这两个有序区间进行操作

经典场景比如:统计逆序对数量

题目

排序数组

leetcode 912

更多排序看这里

class Solution {vector<int>t;
public:vector<int> sortArray(vector<int>& nums) {t.resize(nums.size());sort(nums,0,nums.size()-1);return nums;}void sort(vector<int>&n,int l,int r){if(l>=r)return;int m=(l+r)>>1;sort(n,l,m);sort(n,m+1,r);int i=l,j=m+1,p=l;while(i<=m&&j<=r){if(n[i]<n[j])t[p++]=n[i++];else t[p++]=n[j++];}while(i<=m)t[p++]=n[i++];while(j<=r)t[p++]=n[j++];for(;l<=r;l++)n[l]=t[l];}
};

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

leetcode 315

每当我们判断出n[i]<n[j]时说明从 mid+1j-1都小于i
若最后剩下的是左区间,那么对于剩下的元素 : 右区间所有元素都比它小

class Solution {vector<pair<int,int>>n;vector<pair<int,int>>t;vector<int>cnt;
public:vector<int> countSmaller(vector<int>& nums) {n.resize(nums.size());t.resize(nums.size());cnt.resize(nums.size());for(size_t i=0;i<nums.size();++i){n[i].first=i;n[i].second=nums[i];}sort(0,nums.size()-1);return cnt;}void sort(int l,int r){if(l>=r)return;int mid=(l+r)>>1;sort(l,mid);sort(mid+1,r);int i=l,j=mid+1,p=l;while(i<=mid&&j<=r){if(n[i].second<=n[j].second){t[p++]=n[i];cnt[n[i++].first]+=j-mid-1;}else t[p++]=n[j++];}while(i<=mid){t[p++]=n[i];cnt[n[i++].first]+=r-mid;}while(j<=r)t[p++]=n[j++];for(;l<=r;++l)n[l]=t[l];}
};

翻转对

leetcode 493

双指针尺取

充分利用区间单调性,指针只向一个方向移动

class Solution {vector<int>t;int ans=0;
public:int reversePairs(vector<int>& nums) {t.resize(nums.size());sort(nums,0,nums.size()-1);return ans;}void sort(vector<int>&n,int l,int r){if(l>=r)return;int m=(l+r)>>1;sort(n,l,m);sort(n,m+1,r);int rr=m+1;for(int i=l;i<=m;++i){while(rr<=r&&(long)n[i]>(long)n[rr]*2)rr++;ans+=rr-m-1;}int i=l,j=m+1,p=l;while(i<=m&&j<=r){if(n[i]<n[j])t[p++]=n[i++];else t[p++]=n[j++];}while(i<=m)t[p++]=n[i++];while(j<=r)t[p++]=n[j++];for(;l<=r;l++)n[l]=t[l];}
};

区间和的个数

leetcode 327

区间和问题转换为前缀和相减

枚举左区间每一个i 在右区间尺取合法区间

class Solution {vector<long long>pre;vector<long long>t;int lower,upper,ans=0;
public:int countRangeSum(vector<int>& nums, int lower, int upper) {this->lower=lower;this->upper=upper;int n=nums.size();pre.resize(n+1);t.resize(n+1);for(int i=1;i<=n;++i)pre[i]=pre[i-1]+nums[i-1];sort(pre,0,n);return ans;}void sort(vector<long long>&n,int l,int r){if(l>=r)return;int m=(l+r)>>1;sort(n,l,m);sort(n,m+1,r);int ll=m+1,rr=m+1;for(int i=l;i<=m;++i){while(ll<=r&&n[ll]-n[i]<lower)ll++;while(rr<=r&&n[rr]-n[i]<=upper)rr++;ans+=rr-ll;}int i=l,j=m+1,p=l;while(i<=m&&j<=r){if(n[i]<n[j])t[p++]=n[i++];else t[p++]=n[j++];}while(i<=m)t[p++]=n[i++];while(j<=r)t[p++]=n[j++];for(;l<=r;l++)n[l]=t[l];}
};
http://www.jsqmd.com/news/156249/

相关文章:

  • 2025.11.10上机实验三:C4.5(带有预剪枝和后剪枝)算法实现与测试
  • 中信银行信用卡中心Android高级研发工程师岗位深度解析与技术面试指南
  • 上位机是什么意思:工业4.0中OPC UA协议的应用
  • 2025.10.30非遗声景漫游馆(项目架构文档)
  • 清华大学开源镜像站配置PyTorch源的方法详解
  • 2025最新!8款AI论文软件测评:本科生毕业论文写作全攻略
  • SHEIN高级/资深iOS研发工程师:技术深度解析与面试指南
  • SSH免密登录PyTorch服务器,提高开发效率
  • AI原生应用领域下的AI工作流最佳实践
  • 2025.11.3社区智慧共享资源管理系统(项目概述文档)
  • 2025.10.31非遗声景漫游馆(技术实现文档)
  • 文法定义了一个典型的表达式文法,支持加法和乘法,具有左递归以实现左结合
  • 从文法的开始符号出发,尝试通过一系列最左推导,构造出与输入串完全匹配的语法树
  • 2025.11.5社区智慧共享资源管理系统(部署和运行文档)
  • 2025.10.28校园绿色能源监测与管理MIS系统(功能模块)
  • PyTorch-CUDA-v2.6镜像更新日志:新增支持哪些功能?
  • Springmvc的底层原理流程描述
  • (旧文)聊聊在Android跑RPG Maker游戏那点事
  • 布尔表达式的文法与代码结构在编译原理中属于**中间代码生成**阶段的重要内容
  • 2025.11.1非遗声景漫游馆(用户使用文档)
  • 2025.10.29校园绿色能源监测与管理MIS系统(部署和运行指南)
  • 2025.11.2非遗声景漫游馆(项目完成报告)
  • 2025.10.25故事生成系统介绍
  • 水处理自动化:西门子1500PLC与WinCC7.5的完美结合
  • FIRST/FOLLOW 集是编译原理中语法分析阶段的重要工具,主要用于自顶向下语法分析(如 LL(1) 分析)
  • 质子交换膜燃料电池:稳态与动态建模、仿真分析及特性研究
  • 质子交换膜燃料电池:稳态与动态建模、仿真分析及特性研究
  • 自动驾驶,AutoWareAuto框架全框架梳理思维导图及代码注释。 授人以鱼不如授人以渔,涵...
  • 三菱通过485BD板CRC指令通讯示例(不含详细校验程序)
  • 江湖四门:邪术门派的绝密智慧