(排序算法)归并排序

方法一:

写的归并排序的应用--求逆序对

这里同时进行了排序+计算逆序对

参考这位大佬:Krahets

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++版本的

B站--归并排序

我理解是:

  1. 分治:将数组分为左、右两半,然后对左右半再如此......直到不能再细分(分到只剩最后一个元素)
  2. 合并:两个部分内部是有序的,将它们合并

特别注意这个下标,一不小心就越界了,头皮发麻,特别是感觉自己思路没啥问题的时候------

#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;
}

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jasscical

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值