【编程题】数组中的逆序对(java语言)
题目描述
有一组数,对于其中任意两个数组,若前面一个大于后面一个数字,则这两个数字组成一个逆序对。请设计一个高效的算法,计算给定数组中的逆序对个数。
给定一个int数组A和它的大小n,请返回A中的逆序对个数。保证n小于等于5000。
测试样例:
[1,2,3,4,5,6,7,0],8
返回:7
***方法一***归并方法
思路讲解:
①归并思路
归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
②利用归并排序,在对有序子数组进行merge的同时,累加逆序对,时间复杂度O(nlogn)
代码
import java.util.*;
public class AntiOrder {
public int count(int[] A, int n) {
// write code here
int[] copy=new int[n];
for(int i=0;i<n;i++)
copy[i]=A[i];
return sortCore(A,copy,0,n-1);
}
int sortCore(int[] A,int[] copy,int low,int high){
if(low>=high){
copy[low]=A[low];
return 0;
}
int mid=(low+high)>>1;
int left=sortCore(copy,A,low,mid);
int right=sortCore(copy,A,mid+1,high);
int i=mid,j=high,index=high;
int count=0;
while(i>=low&&j>=mid+1){
if(A[i]>A[j]){
count+=j-mid;
copy[index--]=A[i--];
}else
copy[index--]=A[j--];
}
while(i>=low)
copy[index--]=A[i--];
while(j>=mid+1)
copy[index--]=A[j--];
return count+left+right;
}
}
包含main输入的代码
import java.util.ArrayList;
import java.util.Scanner;
public class Main5 {
public static void main(String[] args) {
int[] A={1,2,3,4,5,6,7,0};
int count= count( A,A.length);
System.out.println(count);
}
public static int count(int[] A, int n) {
// write code here
int[] copy=new int[n];
for(int i=0;i<n;i++)
copy[i]=A[i];
return sortCore(A,copy,0,n-1);
}
private static int sortCore(int[] A,int[] copy,int low,int high){
if(low>=high){
copy[low]=A[low];
return 0;
}
int mid=(low+high)>>1;
int left=sortCore(copy,A,low,mid);
int right=sortCore(copy,A,mid+1,high);
int i=mid,j=high,index=high;
int count=0;
while(i>=low&&j>=mid+1){
if(A[i]>A[j]){
count+=j-mid;
copy[index--]=A[i--];
}else
copy[index--]=A[j--];
}
while(i>=low)
copy[index--]=A[i--];
while(j>=mid+1)
copy[index--]=A[j--];
return count+left+right;
}
}
***方法二***暴力解法
思路讲解
直接两次循环遍历,比较是否为逆序
代码
import java.util.*;
public class AntiOrder {
public int count(int[] A, int n) {
// write code here
int result = 0;
for(int i = 1;i < n;i++){
for(int j = 0;j<i;j++){
if (A[j] > A[i])
result++;
}
}
return result;
}
}