码迷,mamicode.com
首页 > 编程语言 > 详细

36 - 求数组中的逆序对

时间:2015-07-29 12:18:00      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:array

题目描述:http://ac.jobdu.com/problem.php?pid=1348
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
如输入{7,5,6,4}中,共存在5个逆序对:(7,6) (7,5) (7,4) (6,4) (5,4)


解析:

直观思路是:

从第一个数字开始,让它和后面的每个数字比较,找出所有逆序对。时间复杂度O(n2)

改进思路:

只要让一个数字和其他的每个数字比较,那么时间就是O(n2)。那么,基于比较的n^2如何优化呢,我们可以联想到排序过程,基本排序逐个比较是n^2,改进排序算法则是nlogn

采用merge-sort的思路:
将原数组,平均分成左右部分,找出左右子数组中的逆序对(并将左右数组排序),再找出左右子数组合并时的逆序对,将有序的左右数组归并到1个数组。

如:左数组{5,7}, 右数组{4,6},将左右数组合并
因为7大于6,则逆序对数+2(右数组的剩余长度);5 < 6 不产生逆序对;5 > 4,逆序对数+1。
即:
(1)如果现存左数组的最大值大于现存右数组的最大值,则逆序对数 + 右数组的长度;
如果现存左数组的最大值小于现存右数组的最大值,则不存在逆序对;
(2)将左右的最大值,放到缓存数组;使用归并算法将左右最终合并成一个有序的数组。

最终逆序对的总数 = 左的逆序对数 + 右的逆序对数 + 左右合并的逆序对数

#include <iostream>
using namespace std;
int InvertPairCore(int* nums, int* copy, int start, int end);

int InvertPair(int nums[], int length) {
    if (nums == NULL || length <= 0)
        return 0;
    int *copy = new int[length];
    for (int i = 0; i < length; i++)
        copy[i] = nums[i];
    int result = InvertPairCore(nums, copy, 0, length-1);
    delete copy;
    return result;
}

int InvertPairCore(int* nums, int* copy, int start, int end) {
    if (nums == NULL || copy == NULL || start >= end)
        return 0;
    int mid = (start+end) / 2;
    int left_pairs = 0, right_pairs = 0;
    left_pairs = InvertPairCore(copy, nums, start, mid); // 注意此处,输入数组是copy,因为copy已经有序
    right_pairs = InvertPairCore(copy, nums, mid+1, end);

    int count = 0; // 左右字符串相连时的逆序对的个数
    int i = mid, j = end;
    int k = end; // copy index
    // 将左右有序子数组归并成一个有序数组
    while (i >= start && j >= mid+1) {
        if (nums[i] > nums[j]) {
            copy[k--] = nums[i--];
            count += j-mid;
        } else {
            copy[k--] = nums[j--];
        }
    }
    while (i >= start)
        copy[k--] = nums[i--];
    while (j >= mid+1)
        copy[k--] = nums[j--];
    return left_pairs + right_pairs + count;
}

int main() {
    int nums[] = {7,5,6,4};
    cout << InvertPair(nums, sizeof(nums)/sizeof(nums[0])) << endl;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

36 - 求数组中的逆序对

标签:array

原文地址:http://blog.csdn.net/quzhongxin/article/details/47124299

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!