给定一个int数组A和它的大小n,对于这组数能组成的任意两个数组,若前面一个大于后面一个数字,则这两个数字组成一个逆序对。请设计一种高效的算法返回A中存在的逆序对个数。要求n不大于5000。
测试样例:
[1,2,3,4,5,6,7,0],8
返回:7
import java.util.*;
public class AntiOrder {
public int count(int[] A, int n) {
int num = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if(A[i] > A[j]) {
num++;
}
}
}
return num;
}
}
public class Main {
public int count(int[] A, int n) {
// write code here
if(A == null || n < 2 || n > 5000) {
return 0;
}
return sort(A,0,n - 1);
}
public static int sort(int[] arr,int left,int right) {
if(left == right) {
return 0;
}
int mid = left + ((right - left) >> 1);
return sort(arr,left,mid) + sort(arr,mid+1,right) + merge(arr,left,mid,right);
}
public static int merge(int[] arr,int left,int mid, int right) {
int[] help = new int[right - left + 1];
int i = 0;
int p1 = left;
int p2 = mid+1;
int res = 0;
while(p1 <= mid && p2 <= right) {
res += arr[p1] > arr[p2] ? (mid - p1 + 1) : 0;
help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while(p1 <= mid) {
help[i++] = arr[p1++];
}
while(p2 <= right) {
help[i++] = arr[p2++];
}
for(int j = 0;j < help.length;j++) {
arr[left++] = help[j];
}
return res;
}
}
为什么在IDEA能AC,在这里显示可能数组越界,谁能告诉我错在哪了
import java.util.*;
//其实也就是求一个数左边有少个比它大的,排序后p2之前的数就是p2的所有逆序对 (R-p2+1)
public class AntiOrder {
public int count(int[] A,int n) {
if(A == null || n == 0) return 0;
return mergSort(A,0,A.length-1);
}
public int mergSort(int[] arr,int L,int R){
if(L == R) return 0;
int mid = L+ ((R-L) >> 1);
return mergSort(arr,L,mid)+mergSort(arr,mid+1,R)+merg(arr,L,mid,R);
}
public int merg(int[] arr,int L,int mid,int R){
int[] help = new int[R-L+1];
int i = 0;
int count = 0;
int p1 = L;
int p2 = mid+1;
while(p1 <= mid && p2 <= R){
if(arr[p1] > arr[p2]){
count += (mid-L)+1;
help[i++] = arr[p2++];
}else{
help[i++] = arr[p1++];
}
}
while(p1 <= mid){
help[i++] = arr[p1++];
}
while(p2 <= R){
help[i++] = arr[p2++];
}
for (int j = 0; j < help.length; j++) {
arr[L + j] = help[j];
}
return count;
}
} //参考剑指offer,利用归并排序的思想。
public class AntiOrder {
private int counter = 0;
public int count(int[] A, int n) {
if(n == 0) return 0;
int[] aux = new int[n];
countCore(A, aux, n, 0, n - 1);
return counter;
}
private void countCore(int[] A, int[] aux, int n, int lo, int hi) {
if(lo == hi) return;
int mid = (lo + hi) / 2;
//先排好序
countCore(A, aux, n, lo, mid);
countCore(A, aux, n, mid + 1, hi);
int i = mid, j = hi;
//进行归并,从高索引处开始
for(int k = hi; k >= lo; k--) {
if(i < lo) {
aux[k] = A[j--];
}
else if(j < mid + 1) {
aux[k] = A[i--];
}
else if(A[i] < A[j]) aux[k] = A[j--];
else if(A[i] > A[j]) {
aux[k] = A[i--];
counter += (j - mid);
}
else {
aux[k] = A[j--];
}
}
//第一次使用native方法啊。将归并的结果复制到数组A中
System.arraycopy(aux, lo, A, lo, hi - lo + 1);
}
}
import java.util.*;
public class AntiOrder {
int num=0;
public int count(int[] A, int n) {
merge(A,0,n-1);
return num;
}
private void merge(int[] A,int l,int r){
if(l>=r)
return;
int[] tmp=new int[r-l+1];
int mid=(l+r)/2;
merge(A,l,mid);
merge(A,mid+1,r);
int i=0,j=l,k=mid+1;
while(j<=mid&&k<=r){
if(A[j]<=A[k])
tmp[i++]=A[j++];
else{
tmp[i++]=A[k++];
num+=mid-j+1;
}
}
while(j<=mid)
tmp[i++]=A[j++];
while(k<=r)
tmp[i++]=A[k++];
i=0;
for(int m=l;m<=r;m++){
A[m]=tmp[i++];
}
}
}
/*
public class AntiOrder {
int[] treeArr;
private int lowbit(int x){
return x&(-x);
}
private int getSum(int i){
int res=0;
for(;i>0;i-=lowbit(i))
res+=treeArr[i];
return res;
}
private void add(int i,int val,int n){
for(;i<=n;i+=lowbit(i))
treeArr[i]+=val;
}
public int count(int[] A, int n) {
treeArr=new int[n+1];
ArrayList<Integer> uniqueA=new ArrayList<Integer>();
int[] disA=new int[n];
int count=0;
for(int i=0;i<n;i++)
disA[i]=A[i];
Arrays.sort(A);
for(int i=0;i<n;i++){
if(!uniqueA.contains(A[i]))
uniqueA.add(A[i]);
}
for(int i=0;i<n;i++)
disA[i]= uniqueA.indexOf(disA[i])+1;
for(int i=n-1;i>=0;i--){
count+=getSum(disA[i]-1);
add(disA[i],1,n);
}
return count;
}
}
*/
import java.util.*;
public class InversePairs {
public static int count(int[] array, int length) {
if (array == null || length <= 0) {
return 0;
}
//创建辅助数组
int[] copy = new int[length];
for (int i = 0; i < length; i++){
copy[i] = array[i];
}
int result = InversePairsCore(array, copy, 0, length - 1);
return result;
}
//归并排序的合并过程
public static int InversePairsCore(int[] array, int[] copy, int start, int end) {
if (start == end) {
copy[start] = array[start];
return 0;
}
int mid = (end - start) / 2;
//递归调用
int left = InversePairsCore(copy, array, start, start + mid);
int right = InversePairsCore(copy, array, start + mid + 1, end);
//归并
int i = start + mid; // i 初始化为前半段最后一个数字的下标
int j = end; // j 初始化为后半段最后一个数字的下标
int indexCopy = end;
int count = 0; //记录相邻子数组间的逆序数
//每次比较两个末尾值
while (i >= start && j >= start + mid + 1) {
//如果前末尾值大于后末尾值,则有“后序列当前长度”个逆序对
if (array[i] > array[j]) {
copy[indexCopy--] = array[i--];
count += j - mid - start;
}
//否则不构成逆序对
else {
copy[indexCopy--] = array[j--];
}
}
while(i >= start) {
copy[indexCopy--] = array[i--];
}
while(j >= start + mid + 1) {
copy[indexCopy--] = array[j--];
}
return left + right + count;
}
}