2020/12/10 小和問題
阿新 • • 發佈:2020-12-11
裡面有句抖機靈
int mid = left + ((right - left) >> 1);
可以理解為
mid=(L+R)/2
但是這是一種不安全的寫法,因為可能(R+L)溢位
安全的寫法可以表示為:
mid=L+(R-L)/2;
而除以2就可以寫成“>>1”:二進位制右移一位
位運算的時間比常數運算要好
#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;
}