在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
思路使用归并排序
首先要会写归并排序:
public class MergeSort {
private static Comparable[] aux;
public static void sort(Comparable[] a) {
aux = new Comparable[a.length];
sort(a, 0, a.length - 1);
}
private static void sort(Comparable[] a, int lo, int hi) {
if (lo >= hi) return;
int mid = lo + (hi - lo) / 2;
sort(a, lo, mid);
sort(a, mid + 1, hi);
merge(a, lo, mid, hi);
}
private static void merge(Comparable[] a, int lo, int mid, int hi) {
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++) aux[k] = a[k];
for (int k = lo; k <= hi; k++) {
if (i > mid) {
a[k] = aux[j++];
} else if (j > hi) {
a[k] = aux[i++];
// 必须是 less(aux[j], aux[i]),不能为less(aux[i], aux[j])
// 保证归并排序稳定性
} else if (less(aux[j], aux[i])) {
a[k] = aux[j++];
} else {
a[k] = aux[i++];
}
}
}
private static boolean less(Comparable a, Comparable b) {
return a.compareTo(b) < 0;
}
}
答案:
class Solution {
private int[] aux;
public int reversePairs(int[] a) {
if (a == null || a.length == 0) return 0;
aux = new int[a.length];
return getCount(a, 0, a.length - 1);
}
private int getCount(int[] a, int lo, int hi) {
if (lo >= hi) return 0;
int mid = lo + (hi - lo) / 2;
int left = getCount(a, lo, mid);
int right = getCount(a, mid + 1, hi);
if (a[mid] <= a[mid + 1]) {
return left + right;
}
int cross = merge(a, lo, mid, hi);
return left + right + cross;
}
private int merge(int[] a, int lo, int mid, int hi) {
int i = lo, j = mid + 1, count = 0;
for (int k = lo; k <= hi; k++) aux[k] = a[k];
for (int k = lo; k <= hi; k++) {
if (i > mid) {
a[k] = aux[j++];
} else if (j > hi) {
a[k] = aux[i++];
} else if (aux[j] < aux[i]) {
a[k] = aux[j++];
count += mid - i + 1;
} else {
a[k] = aux[i++];
}
}
return count;
}
}
网友评论