35、数组中的逆排序 很好的题目,建议再刷
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字数据范围: 对于%50的数据,size<=10^4 对于%75的数据,size<=10^5 对于%100的数据,size<=2*10^5
示例1
输入
1,2,3,4,5,6,7,0
输出
7
1、只通过50%的笨方法
int InversePairs(vector<int> data) { if (data.size() <= 1) return 0; int len = data.size(); vector<int> dp(len, 0); for (int i = len - 2; i >= 0; --i) { for (int j = i + 1; j < len; ++j) { if (data[i] > data[j]) { //dp[i] = max(dp[i], dp[j] + 1); dp[i]++; } } } return accumulate(dp.begin(), dp.end(), 0) % 1000000007; }
2、牛客上的一种做法,很厉害
https://www.nowcoder.com/profile/872855282/codeBookDetail?submissionId=78340272
int InversePairs(vector<int> data) { if (data.size() == 0) return 0; vector<int> copy(data); // 辅助数组,每次递归后有序 return InversePairsCore(data, copy, 0, data.size() - 1); } int InversePairsCore(vector<int>& data, vector<int>& copy, int begin, int end) { if (begin == end) return 0; int mid = begin + (end - begin) /2; int left = InversePairsCore(copy, data, begin, mid);//这里的一步很绝啊,减少了交换的这一步 int right = InversePairsCore(copy, data, mid + 1, end); int end1 = mid; // 比较从尾端开始 int end2 = end; // 比较从尾端开始 int index_copy = end; // 比较结果存入辅助数组尾端 long res = 0; // 归并排序:相当于两个有序数组合成一个有序表(从尾端开始是为了计数) while (begin<= end1 && mid + 1<= end2) { if (data[end1] > data[end2]) { copy[index_copy--] = data[end1--]; res += end2 - mid; res %= 1000000007; } else copy[index_copy--] = data[end2--]; } while (begin<= end1) copy[index_copy--] = data[end1--]; while (mid + 1<= end2) copy[index_copy--] = data[end2--]; return (left + right + res) % 1000000007; }
InversePairsCore(copy, data, begin, mid)中 copy和data互换位置好评。。。这样就减少了赋值的那一步了。。。。。
二刷:
1、很棒的一道题目,建议多刷
int InversePairsCore(vector<int>& data, vector<int>& copy, int begin, int end) { if (begin == end) return 0; int mid = begin + (end - begin) / 2; int low1 = begin, high1 = mid, low2 = mid + 1, high2 = end; int left = InversePairsCore(copy, data, low1, high1);//这里的一步很绝啊,减少了交换的这一步 int right = InversePairsCore(copy, data, low2, high2); long res = 0; int copyIndex = low1; // 归并排序:相当于两个有序数组合成一个有序表 while (low1 <= high1 && low2 <= high2) { if (data[low1] > data[low2]) { copy[copyIndex++] = data[low1++]; res += high2 - low2 + 1;// data[low1] > data[low2],那么这一次