欢迎大家关注我的微信公众号,同步更新博客,方便查看
小和问题和逆序对问题是归并排序的算法的延伸应用,这篇博客将实现小和问题和逆序对问题的求解
小和问题
- 在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和,求一个数组的小和
- 时间复杂度 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;
}
如有侵权,请联系删除,如有错误,欢迎大家指正,谢谢