zoukankan      html  css  js  c++  java
  • 数组中的逆序对

    题目描述

    在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数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


    解析:这道题的一般想法就是n的平方的复杂度,每个数依次和后面的所有的作比较,如果前面的大于后面的,count++。可是这个结果肯定不是最好的答案,最好的解法是n*log n的复杂度的解法。
    类似于归并排序的解法,把这个数组分成前后两部分,如果前后两部分已经排好序(从小到大),并且已经算出了,前后两部分的各自的逆序对,那这个时候这个数组的逆序对只可能是前半部分
    一个后半部分一个,因为在同一部分的已经找完了(你别管咋找的,就假设找完了),这个时候把前后两部分对比起来看,两个指针,从前往后移前边的指针数字大于后面的了,那么前边部分的
    当前指针后面的所有数都大于后面部分当前指针指向的数字。一直把较小的copy到一个缓存数组中,同时把小的指针后移。终止条件是数组长度为1.

    上代码
    public class Solution {
        public int InversePairs(int [] array) {
            if(array==null||array.length==0){
                return 0;
            }
            int[] copy=new int[array.length];
            int ans=get(array,copy,0,array.length-1);
            return ans;
        }
        public int get(int [] array,int[] copy,int start,int end){
            if(start==end){
                return 0;
            }
            int mid=(start+end)/2;
            int leftcount=get(array,copy,start,mid)%1000000007 ;
            int rightcount=get(array,copy,mid+1,end)%1000000007 ;
            int fir=start;
            int sec=mid+1;
            int i=0;
            int count=0;
            while(fir<=mid&&sec<=end){
                if(array[fir]>array[sec]){
                    copy[i++]=array[sec];
                    sec++;
                    count+=(mid-fir+1);
                    if(count>1000000007){
                        count%=1000000007;
                    }
                    
                }else{
                    copy[i++]=array[fir];
                    fir++;
                }
                
            }
    
            while(fir<=mid){
                  copy[i++]=array[fir];  
                  fir++;
            }
    
            while(sec<=end){
                  copy[i++]=array[sec]; 
                  sec++;
            }
            for(int k=0;k<=end-start;k++){
                array[k+start]=copy[k];
            }
            return (count+leftcount+rightcount)%1000000007 ;
            
            
        }
    }

    其中的copy数组,总是传递索引进去而不是在递归函数里面新建是为了防止超时。





  • 相关阅读:
    网络编程(四)
    网络编程(三)
    网络编程(二)
    网络编程(一)
    异常处理
    Python 的名称空间和作用域
    如何在Java 8中愉快地处理日期和时间
    线段树入门整理、
    最小生成树prim、
    <climits>头文件
  • 原文地址:https://www.cnblogs.com/tobemaster/p/5918531.html
Copyright © 2011-2022 走看看