【C++算法】分治——归并
排序数组
- 题目链接
排序数组https://leetcode.cn/problems/sort-an-array/description/
- 算法原理
- 代码步骤
class Solution {vector<int> tmp;
public:vector<int> sortArray(vector<int>& nums) {tmp.resize(nums.size());merge(nums, 0, nums.size() - 1);return nums;}void merge(vector<int>& nums, int left, int right){if(left >= right) return;int mid = (right + left) >> 1;merge(nums, left, mid);merge(nums, mid + 1, right);int i = 0, 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];}}
};
交易逆序对的总数
- 题目链接
交易逆序对的总数https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/description/
- 算法原理
- 代码步骤
class Solution {vector<int> tmp;
public:int reversePairs(vector<int>& record) {tmp.resize(record.size());return merge(record, 0, record.size() - 1);}int merge(vector<int>& nums, int left, int right){int ret = 0;if(left >= right) return 0;int mid = (left + right) >> 1;ret += merge(nums, left, mid);ret += merge(nums, mid + 1, right);int i = 0, cur1 = left, cur2 = mid + 1;while(cur1 <= mid && cur2 <= right){if(nums[cur1] <= nums[cur2]) {tmp[i++] = nums[cur1++];}else{ret += mid - cur1 + 1;tmp[i++] = 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;}
};
计算右侧小于当前元素的个数
- 题目链接
计算右侧小于当前元素的个数https://leetcode.cn/problems/count-of-smaller-numbers-after-self/description/
- 算法原理
- 代码步骤
class Solution {vector<int> ret;vector<int> index;int tmpNums[100001];int tmpIndex[100001];
public:vector<int> countSmaller(vector<int>& nums) {int n = nums.size();ret.resize(n);index.resize(n);for(int i = 0; i < n; i++){index[i] = i;}mergeSort(nums, 0, n - 1);return ret;}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 i = 0, cur1 = left, cur2 = mid + 1;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 i = left; i <= right; i++){nums[i] = tmpNums[i - left];index[i] = tmpIndex[i - left];}}
};
翻转对
- 题目链接
翻转对https://leetcode.cn/problems/reverse-pairs/description/
- 算法原理
- 代码步骤
class Solution {vector<int> tmp;
public:int reversePairs(vector<int>& nums) {int n = nums.size();tmp.resize(n);return mergeSort(nums, 0, n - 1);}int mergeSort(vector<int>& nums, int left, int right){if(left >= right) return 0;int ret = 0;int mid = (left + right) >> 1;ret += mergeSort(nums, left, mid);ret += mergeSort(nums, mid + 1, right);int cur1 = left, cur2 = mid + 1, i = 0;while(cur1 <= mid && cur2 <= right){while(cur2 <= right && nums[cur1] / 2.0 <= nums[cur2]){cur2++;}ret += right - cur2 + 1;cur1++;}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 i = left; i <= right; i++){nums[i] = tmp[i - left];}return ret;}
};