逆序对的三种解法(归并、树状数组、线段树)
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; } }