数组中的逆序对(分治)

题目描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
输入:

每个测试案例包括两行:

第一行包含一个整数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 }

 
时间: 2024-11-05 06:25:05

数组中的逆序对(分治)的相关文章

数组中的逆序对与归并中的分治思想

首先考虑归并排序: 归并排序为什么能相比普通的排序方法,将时间复杂度从O(n^2)提升至O(nlogn)? 最主要的一点是引入了两个有序数组合并的思想,真正提升效率就是在这个地方. 首先我们考虑,如果两个数组无序的话,比如: 如果使用O(n^2)的方法,在这样一个数组中,每一个数都要跟其他的数比较一下,这样复杂度就为n*n=n^2 而如果这两个数组是有序的呢? 我们用两个指针p1和p2分别指向两个数组的尾部:首先49比97小,97放入排序数组的尾部,因为它是最大的: 然后移动p2至65,再次与4

【Sorting】【Array】数组中的逆序对

数组中的逆序对 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 输入: 每个测试案例包括两行: 第一行包含一个整数n,表示数组中的元素个数.其中1 <= n <= 10^5. 第二行包含n个整数,每个数组均为int类型. 输出: 对应每个测试案例,输出一个整数,表示数组中的逆序对的总数. 样例输入: 4 7 5 6 4 样例输出: 5 思路 分治的思想,统计两边内部的逆序对,以及左右两边之间的逆序对 代码 long

剑指Offer对答如流系列 - 数组中的逆序对

面试题51:数组中的逆序对 题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 问题分析 大多数人的第一反应就是顺序扫描整个数组,对每个数字都和后面的数字比较大小,时间复杂度为O(n^2),效率太低. 利用归并排序的思想,先将数组分解成为n个长度为1的子数组,然后进行两两合并同时排好顺序.(在排序的时候计算逆序对) 归并排序是经典排序算法之一,其核心是将待排数组不断细分,然后排序最后再合并,这是经典的分治策略(分

数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000000007 利用归并排序的思想: 归并排序的改进,把数据分成前后两个数组(递归分到每个数组仅有一个数据项),合并数组,合并时,出现前面的数组值array[i]大于后面数组值array[j]时:则前面数组array[i]~array[mid]都是大于array[j]的,count += mid+1 - i.

编程算法 - 数组中的逆序对 代码(C)

数组中的逆序对 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 在数组中的两个数字如果前面一个数字大于后面的数字, 则这两个数字组成一个逆序对. 输入一个数组, 求出这个数组中的逆序对的总数. 使用归并排序的方法, 辅助空间一个排序的数组, 依次比较前面较大的数字, 算出整体的逆序对数, 不用逐个比较. 时间复杂度: O(nlogn) 代码: /* * main.cpp * * Created on: 2014.6.12 * Author:

剑指offer (36) 数组中的逆序对

题目:在数组中的两个数字如果前面一个数字大于后面一个数字,则这两个数字组成一个逆序对 题解分析: 首先应该想到很简单的一种解法,顺序遍历数组,对每个数,逐个比较该数字和其以后的数字,T(n) = O(n^2) (1)总体的意思就是将数组分成两段,首先求段内的逆序对数量,比如下面两段代码就是求左右两端数组段内的逆序对数量 count += Merge(data, temp, first, mid);//找左半段的逆序对数目 count += Merge(data, temp, mid + 1, e

时间空间效率的平衡:数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000000007 输入描述: 题目保证输入的数组中没有的相同的数字 数据范围: 对于%50的数据,size<=10^4 对于%75的数据,size<=10^5 对于%100的数据,size<=2*10^5 输入例子: 1,2,3,4,5,6,7,0 输出例子: 7

数组中的逆序对-剑指Offer

数组中的逆序对 题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 思路 如果扫描整个数组,每个数字跟后面的数字比较大小,整体的复杂度是O(n^2) 可以利用归并排序的算法的思想,在排序的同时判断前后两个子序列中存在的逆序对,都是从后往前排,如果前面的数大于后面的数,因为都是已经排好序的所以前面的数一定比后面的数都大,逆序对为后面剩下的元素的数量,然后正常排序:若小于,则这个元素不产生逆序对,正常排序.时间复杂度

剑指offer 数组中的逆序对

题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数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 思路:归并排序的思路.具体参考剑指