逆序对的三种解法(归并、树状数组、线段树)

1.逆序对(归并排序)

public class Main{
    public static int count;
    public static int length;
    public static void main(String[] args){ 
        int[] nums={5,3,2,6,1,4};
        length=nums.length;
        mergeSort(nums,0,length-1);
        System.out.println(count);
    }  
    public static void mergeSort(int[] nums,int start,int end){
        if(start>=end){
            return;
        }
        int mid=(start+end)/2;
        mergeSort(nums,start,mid);
        mergeSort(nums,mid+1,end);
        merge(nums,start,mid+1,end);
    }
    public static void merge(int[] nums,int start,int mid,int end){
        int i=start;
        int j=mid;
        int[] res=new int[end-start+1];
        int k=0;        
        while(i<mid && j<=end){
            if(nums[i]<=nums[j]){
                res[k++]=nums[i++];
            }else{
                res[k++]=nums[j++];
                count+=(mid-i);
            }
        }
        while(i<mid){
            res[k++]=nums[i++];
        }
        while(j<=end){
            res[k++]=nums[j++];
        }
        for(int m=0;m<k;m++){
            nums[start+m]=res[m];
        }
    }
}

2.逆序对(离散化+树状数组)

import java.util.*;
public class Main{
    static int[] tree;
    static int length;
    public static void main(String[] args){ 
        int[] nums={55,33,22,66,11,44};
        length=nums.length;
        Node[] nodes=new Node[length];
        tree=new int[length+1];
        for(int i=0;i<length;i++){
            Node tempNode=new Node(nums[i],i+1);
            nodes[i]=tempNode;
        }
        Arrays.sort(nodes,new Comparator<Node>(){
            public int compare(Node a,Node b){
                return a.value-b.value;
            }
        });
        for(int i=0;i<length;i++){
            nums[i]=nodes[i].index;
        }
        int result=0;
        for(int i=0;i<length;i++){
            add(nums[i],1);
            result+=(i-getSum(nums[i])+1);
        }
        System.out.print(result);
    }  
    public static int lowbit(int n){
        return n&(-n);
    }
    public static void add(int n,int val){
        while(n<=length){
            tree[n]+=val;
            n=n+lowbit(n);
        }
    }
    public static int getSum(int n){
        int sum=0;
        while(n>0){
            sum+=tree[n];
            n=n-lowbit(n);
        }
        return sum;
    }
}
class Node{
    int value;
    int index;
    public Node(int value,int index){
        this.value=value;
        this.index=index;
    }
}

3.逆序对(离散化+线段树)

import java.util.*;
public class Main{
    public static void main(String[] args){ 
        int[] nums={55,33,22,66,11,44};
        int length=nums.length;
        Node[] nodes=new Node[length];
        for(int i=0;i<length;i++){
            Node tempNode=new Node(nums[i],i+1);
            nodes[i]=tempNode;
        }
        Arrays.sort(nodes,new Comparator<Node>(){
            public int compare(Node a,Node b){
                return a.value-b.value;
            }
        });
        for(int i=0;i<length;i++){
            nums[i]=nodes[i].index;
        }
        int[] initArray=new int[length];
        SegmentNode rootNode=new buildNode(initArray,0,length-1);
        int result=0;
        for(int i=0;i<length;i++){
            updateNode(rootNode,nums[i],1);
            result+=(i-sumNode(rootNode,1,nums[i])+1);
        }
        System.out.print(result);
    }  
    public static SegmentNode buildNode(int[] nums,int start,int end){
        if(start<end){
            return null;
        }
        SegmentNode node=new SegmentNode(start,end);
        if(start==end){
            node.sum=nums[start];
            return node;
        }
        int mid=(start+end)/2;
        node.left=buildNode(nums,start,mid);
        node.right=buildNode(nums,mid+1,end);
        node.sum=node.left.sum+node.right.sum;
        return node;
    }
    public static void updateNode(SegmentNode node,int index,int value){
        if(node.start==node.end && node.start==index){
            node.sum=value;
            return;
        }
        if(index<node.start || index>node.end){
            return;
        }
        int mid=(node.start+node.end)/2;
        if(index<=mid){
            updateNode(node.left,index,value);
        }else{
            updateNode(node.right,index,value);
        }
        node.sum=node.left.sum+node.right.sum;
    }
    public static int sumNode(SegmentNode node,int left,int right){
        if(node.start==left && node.end==right){
            return node.sum;
        }
        int mid=(node.start+node.end)/2;
        if(right<=mid){
            return sumNode(node.left,left,right);
        }else if(left>mid){
            return sumNode(node.right,left,right);
        }else{
            return sumNode(node.left,left,mid)+sumNode(node.right,mid+1,right);
        }
    }
}
class SegmentNode{
    int start;
    int end;
    int sum;
    SegmentNode left;
    SegmentNode right;
    SegmentNode(int start,int end){
        this.start=start;
        this.end=end;
        this.sum=0;
    }
}
class Node{
    int value;
    int index;
    public Node(int value,int index){
        this.value=value;
        this.index=index;
    }
}

 

posted @ 2018-03-16 17:05  xinyilovestudy  阅读(194)  评论(0编辑  收藏  举报