归并排序思想解决小和问题和逆序对问题

欢迎大家关注我的微信公众号,同步更新博客,方便查看

小和问题和逆序对问题是归并排序的算法的延伸应用,这篇博客将实现小和问题和逆序对问题的求解

小和问题

  • 在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和,求一个数组的小和
  • 时间复杂度 O(N*logN),空间复杂度 O(N)
/*
    @Author: lwl2020
	@Date: 2020-5-20
	@Description: 小和问题的实现
*/

#include <iostream>
#include <vector>
#include <ctime>
using namespace std;

class CSmallSum {
    
    
public:
	int smallSum(vector<int>& arr) {
    
    
		if (arr.size() < 2) {
    
    
			return 0;
		}
		return mergeSortProcess(arr, 0, arr.size() - 1);
	}

private:
	int mergeSortProcess(vector<int>& arr, int left, int right) {
    
    
		if (left == right) {
    
    
			return 0;
		}
		int mid = left + ((right - left) >> 1);
		return mergeSortProcess(arr, left, mid)
			+ mergeSortProcess(arr, mid + 1, right)
			+ merge(arr, left, mid, right);
	}

	int merge(vector<int>& arr, int left, int mid, int right) {
    
    
		int tmpL = left;
		int tmpR = mid + 1;
		int res = 0;
		vector<int> help;
		while (tmpL <= mid && tmpR <= right) {
    
    
			// 生成小和的关键一步
			res += arr.at(tmpL) < arr.at(tmpR) ? arr.at(tmpL) * (right - tmpR + 1) : 0;
			help.push_back(arr.at(tmpL) < arr.at(tmpR) ? arr.at(tmpL++) : arr.at(tmpR++));
		}
		while (tmpL <= mid) {
    
    
			help.push_back(arr.at(tmpL++));
		}
		while (tmpR <= right) {
    
    
			help.push_back(arr.at(tmpR++));
		}
		for (int i = 0; i < help.size(); i++) {
    
    
			arr.at(left + i) = help.at(i);
		}
		return res;
	}
};

int main() {
    
    
	vector<int> arr{
    
     1, 3, 4, 2, 5 };
	int res = CSmallSum().smallSum(arr);
	cout << res << endl;

	system("pause");
	return 0;
}

逆序对问题

  • 在一个数组中,左边的数如果比右边的数大,则这两个数构成一个逆序对,请打印所有逆序对
  • 逆序对问题的求解与小和问题非常相似,也是归并排序的一个延伸应用
/*
    @Author: lwl2020
	@Date: 2020-5-20
	@Description: 逆序对问题的实现
*/

#include <iostream>
#include <vector>
using namespace std;

class CInversionPair {
    
    
public:
	void inversionPair(vector<int>& arr) {
    
    
		if (arr.size() < 2) {
    
    
			return;
		}
		mergeSortProcess(arr, 0, arr.size() - 1);
	}

private:
	void mergeSortProcess(vector<int>& arr, int left, int right) {
    
    
		if (left == right) {
    
    
			return;
		}
		int mid = left + ((right - left) >> 1);
		mergeSortProcess(arr, left, mid);
		mergeSortProcess(arr, mid + 1, right);
		merge(arr, left, mid, right);
	}

	void merge(vector<int>& arr, int left, int mid, int right) {
    
    
		int tmpL = left;
		int tmpR = mid + 1;
		vector<int> help;
		while (tmpL <= mid && tmpR <= right) {
    
    
			//********** 生成并打印逆序对 **********
			if (arr.at(tmpL) > arr.at(tmpR)) {
    
    
				for (int i = 0; i <= mid - tmpL; i++) {
    
    
					cout << "(" << arr.at(tmpL + i) << ", " << arr.at(tmpR) << ")" << endl;
				}
			}
			//**************************************
			help.push_back(arr.at(tmpL) < arr.at(tmpR) ? arr.at(tmpL++) : arr.at(tmpR++));
		}
		while (tmpL <= mid) {
    
    
			help.push_back(arr.at(tmpL++));
		}
		while (tmpR <= right) {
    
    
			help.push_back(arr.at(tmpR++));
		}
		for (int i = 0; i < help.size(); i++) {
    
    
			arr.at(left + i) = help.at(i);
		}
	}
};

int main() {
    
    
	vector<int> arr{
    
     1, 5, 3, 2, 4 };
	CInversionPair().inversionPair(arr);

	system("pause");
	return 0;
}

如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢

猜你喜欢

转载自blog.csdn.net/xiao_ma_nong_last/article/details/106231175