数组中的逆序对(分治)

题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
输入:
每个测试案例包括两行:
第一行包含一个整数n,表示数组中的元素个数。其中1 <= n <= 10^5。
第二行包含n个整数,每个数组均为int类型。
输出:
对应每个测试案例,输出一个整数,表示数组中的逆序对的总数。
样例输入:
4
7 5 6 4
样例输出:
5

1.直接的做法是逐个统计,复杂度是N^2,

2.可以利用归并排序的思想,在排序过程中统计逆序对的个数。时间复杂度依然是 N*Log(N)。 可以从代码中看到,只是比归并排序多了一句代码:cnt += (n1 - i);

由于最终个数可能超过int,这里用long long


 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 long long mergeAndCount(int arr[], int l, int m, int r){
 7     long long cnt = 0;
 8     int n1 = m - l + 1;
 9     int n2 = r - m;
10     int i, j, k;
11     int L[n1], R[n2];
12     for(i = 0; i < n1; i++){
13         L[i] = arr[l + i];
14     }
15     for(i = 0; i < n2; i++){
16         R[i] = arr[m + 1 + i];
17     }
18     i = 0; 
19     j = 0;
20     k = l;
21     //从小到大排序 
22     while(i < n1 && j < n2){
23         if(L[i] <= R[j]){
24             arr[k] = L[i];
25             i++;
26         } else{
27             arr[k] = R[j];
28             cnt += (n1 - i);
29             j++;
30         }
31         k++;
32     }
33 
34     while(i < n1){
35         arr[k++] = L[i];
36         i++;
37     }
38 
39     while(j < n2){
40         arr[k++] = R[j];
41         j++;
42     }
43     
44     return cnt;
45 
46 }
47 
48 long long MergeSortAndCount(int arr[], int l, int r){
49     long long cnt = 0, cnt1, cnt2, cnt3;
50     if(l >= r)
51         return 0;
52     else {
53         int middle = l + (r - l) / 2;
54         cnt1 = MergeSortAndCount(arr, l, middle);
55         cnt2 = MergeSortAndCount(arr, middle + 1, r);
56         cnt3 = mergeAndCount(arr, l, middle, r);
57     }
58     return cnt1 + cnt2 + cnt3;
59 }
60 
61 int main(){
62     int n;
63     cin >> n;
64     int *arr = new int [n];
65     for(int i = 0; i < n; i++)
66         cin >> arr[i];
67     cout << MergeSortAndCount(arr, 0, n - 1) << endl;
68     return 0;
69 }

 

 
posted @ 2016-08-21 23:30  琴影  阅读(559)  评论(0编辑  收藏  举报