剑指offer 编程题(34):数组中的逆序对

这道题真是难理解!!!!

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:

题目保证输入的数组中没有的相同的数字
数据范围:
对于%50的数据,size<=10^4
对于%75的数据,size<=10^5
对于%100的数据,size<=2*10^5

class Solution {
public:
    int res=0;
    int InversePairs(vector<int> data) {
        if(data.size()==0||data.size()==1)
            return 1000000007;
        vector<int> dup(data.size());
        sort(data,dup,0,data.size()-1);
        return res%1000000007;

    }


    void sort(vector<int> &data,vector<int> &dup,
              int low,int high)
        {
        if(low>=high)
            return;
        int mid=(low+high)/2;
        sort(data,dup,low,mid);
        sort(data,dup,mid+1,high);
        merge_sort(data,dup,low,mid,high);
        return;

    }



    void merge_sort(vector<int> &data,vector<int> &dup,
                   int low,int mid,int high )
        {
        int arr1=low,arr2=mid+1;
        for(int i=low;i<=high;++i)
            dup[i]=data[i];
        for(int i=low;i<=high;++i)
            {
            if(arr1>mid)
                data[i]=dup[arr2++];
            else if(arr2>high)
                data[i]=dup[arr1++];
            else if(dup[arr1]<dup[arr2])
                data[i]=dup[arr1++];
            else{
                data[i]=dup[arr2++];
                res+=mid-arr1+1;
                res%=1000000007;
            }
        }
        return;
    }
class Solution {
public:
    int InversePairs(vector<int> data) {
        if(data.size()<2)
            return 0;
        return mergesort(data,0,data.size()-1);
    }
    int mergesort(vector<int> &data,int begin,int end){
        if(begin==end)
            return 0;
        int mid = (begin+end)/2;
        int left = mergesort(data,begin,mid);
        int right = mergesort(data,mid+1,end);
        vector<int> temp(end-begin+1);
        int i=begin,j=mid+1;
        int cur=0,ret=0;
        while(i<=mid && j<=end){
            if(data[i]<=data[j])
                temp[cur++]=data[i++];
            else{
                temp[cur++]=data[j++];
                ret =(ret + mid-i+1)%1000000007;
            }
        }
        while(i<=mid)
            temp[cur++]=data[i++];
        while(j<=end)
            temp[cur++]=data[j++];
        for(int i=begin;i<=end;i++){
            data[i]=temp[i-begin];
        }
        return (ret+left+right)%1000000007;
    }
};
class Solution {
public:
    int InversePairs(vector<int> data) {
        if(data.size()<2)
            return 0;
        return mergesort(data,0,data.size()-1);
    }
    int mergesort(vector<int> &data,int begin,int end){
        if(begin==end)
            return 0;
        int mid = (begin+end)/2;
        int left = mergesort(data,begin,mid);
        int right = mergesort(data,mid+1,end);
        vector<int> temp(end-begin+1);
        int i=begin,j=mid+1;
        int cur=0,ret=0;
        while(i<=mid && j<=end){
            if(data[i]<=data[j])
                temp[cur++]=data[i++];
            else{
                temp[cur++]=data[j++];
                ret =(ret + mid-i+1)%1000000007;
            }
        }
        while(i<=mid)
            temp[cur++]=data[i++];
        while(j<=end)
            temp[cur++]=data[j++];
        for(int i=begin;i<=end;i++){
            data[i]=temp[i-begin];
        }
        return (ret+left+right)%1000000007;
    }
};

(O(n)复杂度)

public class Solution {  

    /* 

    思路如下: 
    借助一个数组hash,统计array从后往前的情况下,到第i位时候,i后面每个数字出现的次数 

    1. 从后往前遍历array, hash数组记录数字array[i]已出现的次数 
    2. 对于数字array[i],统计 array[x](此处 x>i)的的部分,小于array[i]的数字总数 count 
      count 等于hash数组中 hash[x]的和(此处 x < array[i]) 
    3. count即为 array 数组中, 以第i位开始的子数组的逆序数 
    */  
    public int InversePairs(int [] array) {  
        if(array == null || array.length == 0) return 0;  

        int[] hash = new int[10];  
        int i = array.length-1;  

        int ans = 0;  

        for(; i>= 0; i--){  
            hash[array[i]] ++;  
            ans += countInversePairs(hash, array[i]);  
        }  
        return ans;  
    }  

    private int countInversePairs(int[] hash, int target){  
        int count = 0;  
        for(int i = 0; i < target; i++){  
            count += hash[i];  
        }  
        return count;  
    }  


}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值