方法一:
写的归并排序的应用--求逆序对
这里同时进行了排序+计算逆序对
class Solution {
public:
int reversePairs(vector<int>& nums) {
vector<int> tmp(nums.size(), 0);
return mergeSort(nums, tmp, 0, nums.size() - 1);
}
private:
int mergeSort(vector<int>& nums, vector<int>& tmp, int l, int r){
if(l >= r) return 0;
int m = l + (r - l) / 2;
int res = mergeSort(nums, tmp, l, m) + mergeSort(nums, tmp, m + 1, r);
int i = l, j = m + 1;
// tmp 暂存 l ~ r 上的数字
for(int k = l; k <= r; k++){
tmp[k] = nums[k];
}
// 用 k 来标志nums每一个位置上,该选择左、右上的哪个数字
// i -- 左数组, j -- 右数组
for(int k = l; k <= r; k++){
if(i == m + 1) nums[k] = tmp[j++]; //若左数组合并完,则把右边剩下全部放入nums
else if( j == r + 1 || tmp[i] <= tmp[j]) nums[k] = tmp[i++]; //右数组合并完或者左边小于右边,则把左边(或剩下)的放入nums
else{ // 左边当前开始的位置大于右边,所以右边加入nums,并计算 左当前位置 到 左结束位置的距离 作为逆序对数
nums[k] = tmp[j++];
res += m - i + 1;
}
}
return res;
}
};
方法二:
这位大佬讲的很清晰,自己跟着实现了一遍C++版本的
我理解是:
- 分治:将数组分为左、右两半,然后对左右半再如此......直到不能再细分(分到只剩最后一个元素)
- 合并:两个部分内部是有序的,将它们合并
特别注意这个下标,一不小心就越界了,头皮发麻,特别是感觉自己思路没啥问题的时候------
#include <iostream>
#include <vector>
using namespace std;
// 1.合并
void merge(vector<int> &nums, int l, int m, int r){
int L_size = m-l;
int R_size = r-m+1;
vector<int> left, right;
left.resize(L_size); //创建左数组
right.resize(R_size);
int i, j;
for(i=l; i<m; i++){ // 将左边放到一块 ,踩坑---细节 i = l,因为后面递归会重复调用merge函数,所以 i 初始值并不是等于 0,应该等于 l
left[i - l] = nums[i];
}
for(j=m; j<=r; j++){ // 将右边放到一块
right[j-m] = nums[j];
}
i = 0; j = 0; int k = l;
while(i<L_size && j<R_size){ //左右比较大小,将小的元素放进结果nums ,有一方达到顶端就停止
if(left[i] < right[j]){
nums[k] = left[i];
k++;
i++;
}else{
nums[k] = right[j];
k++;
j++;
}
}
while(i < L_size){ // 若左边或右边还有元素剩余,则把剩余元素 依次添加到结果nums后面
nums[k] = left[i];
k++;
i++;
}
while(j < R_size){
nums[k] = right[j];
k++;
j++;
}
}
// 2.分治
void merge_sort(vector<int> &nums, int l, int r){
int m = (l + r)/2;
if(l == r) {
return;
}
else{
merge_sort(nums, l, m);
merge_sort(nums, m+1, r);
merge(nums, l, m+1, r);
}
}
// 3.打印数组
void printVec(vector<int> &nums){
for(auto n:nums){
cout << n << " ";
}
cout<<endl;
}
int main(){
vector<int> nums = {6, 8, 7, 9, 2, 10, 1, 4, 3, 5};
int l = 0, m = nums.size()/2+1, r = nums.size()-1;
//merge(nums, l, m, r);
merge_sort(nums, l, r);
printVec(nums);
return 0;
}