总结的部分题目思路与代码,待完善。
【剑指offer-第二版】部分题目与解答【C++版本】
题目:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如在数组{7,5,6,4}中,一共存在5个逆序对。
解题思路:
1.强解的复杂度太高了。
2.使用二分的思路来求解。具体解题思路见书
可以AC的解法【C++版本】
#include <iostream>
#include <vector>
using namespace std;
int InversePairs(vector<int> data);
int InversePairsCore(vector<int> &data, vector<int> &tmp, int start, int end);
int main()
{
//测试用例
vector<int> data{ 1,2,3,4,5,6,7,0 };
cout << InversePairs(data) << endl;
system("pause");
return 0;
}
int InversePairs(vector<int> data) {
int size = data.size();
if (size <= 1)return 0;
vector<int> tmp = data;
int resu = InversePairsCore(data, tmp, 0, size - 1);
return resu;
}
int InversePairsCore(vector<int> &data, vector<int> &tmp, int start, int end) {
if (start == end) {
tmp[start] = data[start];
return 0;
}
int length = (start + end) / 2;
//这里递归很不好理解,每次返回data都是有序的(调用内部对data,即函数内部的tmp排序)
//出来过后data有序了,又使用data对tmp排序,这样外部的data又是有序的了
int low = InversePairsCore(tmp, data, start, length);
int high = InversePairsCore(tmp, data, length + 1, end);
int i = length, j = end, index = end;
long long cnt = 0; //牛客网的题最后结果比较大,用long long来存
while (i >= start && j >= (length + 1)) {
if (data[i] > data[j]) {
tmp[index--] = data[i--];
cnt += j - length;
}
else {
tmp[index--] = data[j--];
}
}
for (; i >= start; i--) {
tmp[index--] = data[i];
}
for (; j >= (length + 1); j--) {
tmp[index--] = data[j];
}
return static_cast<int>((low + high + cnt) % 1000000007); //需要求模
}