文章目录
- 简介
- 排序数组
- 原理
- 代码
- 交易逆序对的总数
- 原理
- 代码跑的过程
- 代码
- 计算右侧小于当前元素的个数
- 原理
- 代码
- 翻转对
- 代码
简介
大家好,这里是jiantaoyab,这篇文章给大家带来的是归并类型相关的题目练习和解析,涉及到递归的题目大家可以画递归展开图来方便理解,后面的题目有点绕,大家耐心想想就能理解,希望大家能相互讨论进步
排序数组
https://leetcode.cn/problems/sort-an-array/
原理
递归展开图
代码
class Solution {vector<int> tmp; //辅助数组
public://归并排序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;//合并2个有序数组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];}}vector<int> sortArray(vector<int>& nums) {tmp.resize(nums.size());MergeSort(nums, 0, nums.size() - 1);return nums;}
};
交易逆序对的总数
https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof
原理
代码跑的过程
代码
class Solution {vector<int> tmp;
public:int MergeSort(vector<int>& record, int left, int right){if (left >= right) return 0;// 没有逆序对了int ret = 0; //统计有多少逆序对int mid = (left + right) >> 1 ;//1.先求出左边区间和右边区间有多少逆序对// [left,mid] [mid+1,right]ret += MergeSort(record, left, mid);ret += MergeSort(record, mid + 1, right);//2.左边区间找一个,右边区间找一个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 = left; j <= right; j++){record[j] = tmp[j - left];}return ret;}int reversePairs(vector<int>& record) {tmp.resize(record.size());return MergeSort(record, 0, record.size() - 1);}
};
计算右侧小于当前元素的个数
https://leetcode.cn/problems/count-of-smaller-numbers-after-self/
原理
用到上一题的降序解法:找出该数之后有多少个比我小,这里创建的index是和nums元素绑定的,要不断的更改,所以给index创建了一个tmp_index
代码
class Solution {vector<int> index; //nums中元素的下标vector<int> ret; //最终的结果int tmp_nums [1000000]; //nums的辅助数组int tmp_index[1000000]; //index的辅助数组
public:void MergeSort(vector<int>& nums, int left,int right){if( left >= right) return ;int mid = (left + right) >> 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]) {tmp_nums[i] = nums[cur2];tmp_index[i] = index[cur2];i++;cur2++;}else{ret[index[cur1]] += right - cur2 + 1;tmp_nums[i] = nums[cur1];tmp_index[i] = index[cur1];i++;cur1++;}}while(cur1 <= mid){tmp_nums[i] = nums[cur1];tmp_index[i] = index[cur1];i++;cur1++;}while(cur2 <= right){tmp_nums[i] = nums[cur2];tmp_index[i] = index[cur2];i++;cur2++;}for(int j = left; j <= right; j++){nums[j] = tmp_nums[j - left];index[j] = tmp_index[j - left];}}vector<int> countSmaller(vector<int>& nums) {ret.resize(nums.size());index.resize(nums.size());//记录原始数组下标for(int i = 0; i < nums.size(); i++){index[i] = i;}MergeSort(nums, 0 , nums.size() - 1 );return ret;}
};
翻转对
https://leetcode.cn/problems/reverse-pairs/
代码
class Solution {int tmp_nums[50000];
public:int MergeSort(vector<int>& nums, int left, int right){if(left >= right) return 0;int ret = 0;int mid = (right + left) >> 1;ret += MergeSort(nums, left, mid);ret += MergeSort(nums, mid + 1, right);int cur1 = left, cur2 = mid + 1, i = left;//1.先统计翻转对数量while(cur1 <= mid) //固定cur1{//当cur2的2倍比ur1大的时候,cur2++while(cur2 <= right && nums[cur2] >= nums[cur1] / 2.0) cur2++;if(cur2 > right) break;ret += right -cur2 + 1;cur1++;}//2.再合并数数组cur1 = left, cur2 = mid + 1;while(cur1 <= mid && cur2 <= right){tmp_nums[i++] = nums[cur1] >= nums[cur2] ? nums[cur1++] : nums[cur2++];}//处理剩下的元素while(cur1 <= mid) tmp_nums[i++] = nums[cur1++];while(cur2 <= right) tmp_nums[i++] = nums[cur2++];for(int j = left; j <= right; j++){nums[j] = tmp_nums[j]; //i是从left开始的}return ret;}int reversePairs(vector<int>& nums) {return MergeSort(nums, 0, nums.size()-1);}
};