求逆序对数
https://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5?tpId=13&tqId=11188&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数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
思路: 使用归并排序,merge过程中 因为保证了 左侧数组 与 右侧数组 分别有序,所以在merge过程中统计逆序对数
对于数组 :
如果 a[i] > a[j] then j ++; 这样保证了 一旦出现 a[i] <= a[j] 的时候, a[i] > a[m + 1 -> j - 1] 得到由(
a[i] , a[m+1 : j - 1]
)构成的逆序对数 j - 1 - m 对;
#include <iostream> #include <vector> #include <cstdio> #define DEBUG using namespace std; #define MOD 1000000007 class Solution { public: int cnt = 0; void merge(int l, int m, int r, vector<int>& a) { int i = l, j = m + 1, k = r; vector<int>t; while(i <= m || j <= r) { if(i <= m && j <= r) { if(a[i] > a[j]){ t.push_back(a[j ++]); }else{ cnt = ( cnt % MOD + ( j - m - 1) % MOD) % MOD; t.push_back(a[i ++]); } } else if(i <= m) { cnt = ( cnt % MOD + ( j - m - 1) % MOD) % MOD; t.push_back(a[i ++]); } else { t.push_back(a[j ++]); } } for(int i = l; i <= r; i ++) a[i] = t[i - l]; } void divide(int l, int r, vector<int>& a) { if (l < r){ int m = l + (r - l) / 2; divide(l, m, a); divide(m + 1, r, a); merge(l, m, r, a);/* cout << "l:" <<l << " m + 1: "<< m + 1 << " r:" << r<<endl; cout <<"cnt= " <<cnt <<endl; for(int i = l; i <= r; i ++) { cout << a[i] << " "; }cout <<endl;*/ } } int InversePairs(vector<int>& data) { divide(0, data.size() - 1, data); return cnt; } }; int main() { #ifdef DEBUG freopen("input.txt", "r", stdin); #endif // DEBUG vector<int>d; int n, t; cin>>n; for(int i = 0; i < n; i ++){ cin>>t; d.push_back(t); } Solution sol; cout << sol.InversePairs(d) << endl; for(int i = 0; i < n; i ++) cout << d[i] << " " ; return 0; } /* 7 4 5 6 7 3 4 5 */