1.归并排序
#include<iostream>
#include<vector>
using namespace std;
void merge(vector<int>& nums, int begin, int mid, int end) {
vector<int> ret(nums.size(),0);
int p = begin;
int i = begin;
int j = mid + 1;
while (i <= mid&&j <= end) {
if (nums[i]<nums[j]) {
ret[p++] = nums[i++];
}
else {
ret[p++] = nums[j++];
}
}
while (i <= mid) {
ret[p++] = nums[i++];
}
while (j <= end) {
ret[p++] = nums[j++];
}
for (int m = begin; m <= end; ++m) {
nums[m] = ret[m];
}
}
void mergeSort(vector<int>& nums, int begin, int end) {
if (begin == end) return;
int mid = (end - begin) / 2 + begin;
mergeSort(nums, begin, mid);
mergeSort(nums, mid + 1, end);
merge(nums, begin, mid, end);
}
void mergeSort(vector<int>& nums) {
if (nums.empty()) return;
int begin = 0;
int end = nums.size() - 1;
mergeSort(nums, begin, end);
for (int i = 0; i<nums.size(); ++i) {
cout << nums[i] << " ";
}
}
int main() {
int n;
while (cin >> n) {
vector<int> nums(n, 0);
for (int i = 0; i<n; ++i) {
int val; cin >> val;
nums[i] = val;
}
mergeSort(nums);
cout << endl;
}
return 0;
}
2. 剑指offer-数组中的逆序对问题
(1)第一部分是牛客网AC代码
class Solution {
private:
long long merge(vector<int>& nums,
vector<int>& copy,
long long begin, long long mid, long long end) {
long long cnt = 0;
long long p = end;
long long i = mid;
long long j = end;
while (i >= begin &&j > mid) {
if (nums[i] > nums[j]) {
copy[p--] = nums[i--];
cnt += j - mid;
}
else {
copy[p--] = nums[j--];
}
}
while (i >= begin) {
copy[p--] = nums[i--];
}
while (j > mid) {
copy[p--] = nums[j--];
}
for (long long m = begin; m <= end; ++m) {
nums[m] = copy[m];
}
return cnt;
}
long long mergeSort(vector<int>& nums,
vector<int>& copy,
long long begin, long long end) {
if (begin >= end) return 0;
long long mid = (end - begin) / 2 + begin;
long long lCount = mergeSort(nums, copy,begin, mid);
long long rCount = mergeSort(nums, copy,mid + 1, end);
long long crossCount = merge(nums, copy,begin, mid, end);
return lCount + rCount + crossCount;
}
long long mergeSort(vector<int>& nums) {
if (nums.empty()) return 0;
long long begin = 0;
long long end = nums.size() - 1;
vector<int> copy(nums.begin(),nums.end());
return mergeSort(nums, copy,begin, end);
}
public:
long long InversePairs(vector<int> data) {
if (data.empty()) return 0;
return mergeSort(data) % 1000000007;
}
};
(2)VS下测试代码:
#include<iostream>
#include<vector>
using namespace std;
int merge(vector<int>& nums, int begin, int mid, int end) {
vector<int> tmp(nums.size(),0);
int cnt = 0;
int p = end;
int i = mid;
int j = end;
while (i >= begin &&j > mid ) {
if (nums[i] > nums[j]) {
tmp[p--] = nums[i--];
cnt += j - mid;
}
else {
tmp[p--] = nums[j--];
}
}
while (i >= begin) {
tmp[p--] = nums[i--];
}
while (j > mid) {
tmp[p--] = nums[j--];
}
for (int m = begin; m <= end; ++m) {
nums[m] = tmp[m];
}
return cnt;
}
int mergeSort(vector<int>& nums, int begin, int end) {
if (begin == end) return 0;
int mid = (end - begin) / 2 + begin;
int lCount = mergeSort(nums,begin, mid);
int rCount = mergeSort(nums, mid + 1,end);
int crossCount = merge(nums,begin, mid,end);
return lCount + rCount + crossCount;
}
int mergeSort(vector<int>& nums) {
if (nums.empty()) return 0;
int begin = 0;
int end = nums.size() - 1;
return mergeSort(nums, begin, end);
}
int main() {
int n;
while (cin >> n) {
vector<int> nums(n, 0);
for (int i = 0; i<n; ++i) {
int val; cin >> val;
nums[i] = val;
}
cout<<mergeSort(nums)<<endl;
for (int i = 0; i < nums.size(); ++i) {
cout << nums[i] << " ";
}
cout << endl;
}
system("pause");
return 0;
}
VS下测试代码和牛客网通过的代码有一点小区别,测试代码下的辅助矩阵是临时的,但是在牛客网上可能由于测试实例的数据较多,导致复杂度过大无法通过,后来在入口处定义了一个辅助矩阵,传引用的方式一直使用,同时将计数器声明为long long 类型,才通过所有测试用例。
3. leetcode 315 Count of Smaller Number After Self
测试网址:https://leetcode.com/problems/count-of-smaller-numbers-after-self/
AC代码:
class Solution {
private:
void merge(vector<pair<int,int>>& record,vector<int>& count, int begin, int mid, int end) {
vector<pair<int, int>> tmp;
int i = begin;
int j = mid +1;
while (i <= mid&&j <= end ) {
if (record[i].first <= record[j].first) {
count[record[i].second] += j - 1 - mid;
tmp.push_back(record[i++]);
}
else {
tmp.push_back(record[j++]);
}
}
while (i <= mid) {
count[record[i].second] += j - 1 - mid;
tmp.push_back(record[i++]);
}
while (j <= end) {
tmp.push_back(record[j++]);
}
for (int m = begin; m <= end; ++m) {
record[m] = tmp[m - begin];
}
}
void mergeSort(vector<pair<int,int>>& record,vector<int>&ret, int begin, int end) {
if (begin == end) return;
int mid = (end - begin) / 2 + begin;
mergeSort(record,ret, begin, mid);
mergeSort(record,ret, mid + 1,end);
merge(record,ret,begin, mid,end);
}
void mergeSort(vector<int>& nums,vector<int>& ret) {
if (nums.empty()) return;
int begin = 0;
int end = nums.size() - 1;
vector<pair<int, int>> val2index;
for (int i = 0; i < nums.size(); ++i) {
val2index.push_back(pair<int,int>(nums[i],i));
}
mergeSort(val2index,ret, begin, end);
}
public:
vector<int> countSmaller(vector<int>& nums) {
if(nums.empty()) return {};
vector<int> ret(nums.size(),0);
mergeSort(nums,ret);
return ret;
}
};
VS下测试代码:
#include<iostream>
#include<vector>
using namespace std;
//现在的问题是我如何记录下每个数,以及它的逆序对
//
void merge(vector<pair<int,int>>& record,vector<int>& count, int begin, int mid, int end) {
vector<pair<int, int>> tmp;
int i = begin;
int j = mid +1;
while (i <= mid&&j <= end ) {
if (record[i].first <= record[j].first) {
count[record[i].second] += j - 1 - mid;
tmp.push_back(record[i++]);
}
else {
tmp.push_back(record[j++]);
}
}
while (i <= mid) {
count[record[i].second] += j - 1 - mid;
tmp.push_back(record[i++]);
}
while (j <= end) {
tmp.push_back(record[j++]);
}
for (int m = begin; m <= end; ++m) {
record[m] = tmp[m - begin];
}
}
void mergeSort(vector<pair<int,int>>& record,vector<int>&ret, int begin, int end) {
if (begin == end) return;
int mid = (end - begin) / 2 + begin;
mergeSort(record,ret, begin, mid);
mergeSort(record,ret, mid + 1,end);
merge(record,ret,begin, mid,end);
}
void mergeSort(vector<int>& nums,vector<int>& ret) {
if (nums.empty()) return;
int begin = 0;
int end = nums.size() - 1;
vector<pair<int, int>> val2index;
for (int i = 0; i < nums.size(); ++i) {
val2index.push_back(pair<int,int>(nums[i],i));
}
mergeSort(val2index,ret, begin, end);
for (int i = 0; i < val2index.size(); i++) {
cout << val2index[i].first << " " << val2index[i].second << endl;
}
}
int main() {
int n;
while (cin >> n) {
vector<int> nums(n, 0);
for (int i = 0; i<n; ++i) {
int val; cin >> val;
nums[i] = val;
}
vector<int> ret(nums.size(),0);
mergeSort(nums,ret);
for (int i = 0; i<ret.size(); ++i) {
cout << ret[i] << " ";
}
cout << endl;
}
system("pause");
return 0;
}
4. leetcode 493 Reverse Pair
网址:https://leetcode.com/problems/reverse-pairs/
注意这一题的条件和剑指offer中的逆序对条件有所不同,该题逆序对满足条件为 i < j && nums[i] > 2 * nums[j] ,这样的 (i ,j) 才满足条件,解法上大同小异,需要注意控制判断条件,且不要漏算和多算,代码后续补充。