【35】数组中的逆序对

来源:互联网 发布:大拿韩代 知乎 编辑:程序博客网 时间:2024/06/05 18:14

【35】数组中的逆序对

时间限制:1秒
空间限制:32768K

本题知识点: 数组

题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,
则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数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
牛客网题目链接:点击这里

方法一:两个for循环,时间复杂度n^2.

2016/9/6暴力解法已经无法通过测试,提示复杂度过高,运行超时

class Solution {public:    int InversePairs(vector<int> data) {        int count=0;        if(data.empty()) return count;        for(int i=0; i<data.size(); i++)        {            for(int j=i+1; j<data.size(); j++)            {                if(data[i]>data[j]) count++;            }        }        return count;    }};

方法二:从插入排序的角度考虑.

因为插入排序的交换次数就是逆序对的个数。但是插入排序的时间复杂度也是O(n^2).因此排除。

方法三:归并排序,从局部有序到整体有序

时间复杂度O(nlog(n)),稳定排序
算法代码:

class Solution {    int merge_sort(vector<int> &data, int left, int right, vector<int> &temp)    {        if(left>=right) return 0;        int sum=0;        int center=(left+right)/2;        sum+=merge_sort(data,left,center,temp);        sum+=merge_sort(data,center+1,right,temp);        int i=center,j=right;        int p=right;        while(i>=left && j>center)        {            if(data[i]>data[j])             {                temp[p--]=data[i--];                sum=sum+(j-center);                if(sum>1000000007)                    sum=sum%1000000007;  //求余应该加在此处。            }            else            {                temp[p--]=data[j--];            }        }        while(i>=left)        {            temp[p--]=data[i--];        }        while(j>center)        {            temp[p--]=data[j--];        }        for(int k=left; k<=right; k++)        {            data[k]=temp[k];        }           return sum;             }public:    int InversePairs(vector<int> data) {        //归并排序        vector<int> temp(data.size());        int result=0;        result=merge_sort(data,0,data.size()-1,temp);        return result;    }};

说明:可以考虑辅助容器在merge函数内部开辟和取消

VS2010代码:

#include<iostream>#include<vector>using namespace std;class Solution {public:    int InversePairs(vector<int> data) {        if(data.empty()) return 0;        int Num=0;        //在不改变data的情况下,就需要对data进行复制操作        vector<int> dataCopy;        dataCopy.resize(data.size());        for(int i=0; i!=data.size(); i++)        {            dataCopy[i]=data[i];        }        //设置空的辅助数组        vector<int> Associate;        Associate.resize(data.size());        Num=Mergesort(dataCopy, Associate, 0, dataCopy.size()-1 );        return Num;    }    //改进的归并排序    int Mergesort(vector<int> &Array, vector<int> &Associate, int begin, int end)    {        if(begin>=end) return 0;        //定义该分组内的逆序对数        int count=0;        int Mid=(begin+end)/2;        count=count+Mergesort(Array, Associate, begin, Mid);        count=count+Mergesort(Array, Associate, Mid+1, end);        int p1=Mid,p2=end;        int p3=end;        while(begin<=p1 && Mid<p2)        {            if(Array[p1]>Array[p2])            {                count=count+(p2-Mid);  //程序逻辑正确,出现问题是因为把p2写成了end                Associate[p3]=Array[p1];                p1--;p3--;            }            else            {//题目中提示说不考虑相等的情况,因此这里为小于                Associate[p3]=Array[p2];                p2--;p3--;            }        }        while(p1<begin && p2>Mid) //p1已完,p2还未复制完        {            Associate[p3]=Array[p2];            p2--;p3--;        }        while(p1>=begin && p2==Mid) //p2已完,p1未完        {            Associate[p3]=Array[p1];            p1--;p3--;        }        //将辅助数组中已排序好的元素赋给Array        for(int i=begin;i<=end; i++)        {            Array[i]=Associate[i];        }        return count;    }};int main(){    Solution s1;    vector<int> test1;    test1.push_back(1);    test1.push_back(2);    test1.push_back(3);    test1.push_back(4);    test1.push_back(5);    test1.push_back(6);    test1.push_back(7);    test1.push_back(0);    //test1.push_back(7);    //test1.push_back(5);    //test1.push_back(6);    //test1.push_back(4);    cout<<s1.InversePairs(test1)<<endl;    cout<<int(1000000007)<<endl;    cout<<int(1000000007)<<endl;}

说明:

1.逻辑应该没有问题了,本地测试通过。
牛客网一直提示说:出现问题,请稍后重试。

0 0
原创粉丝点击