有一組數,對於其中任意兩個數組,若前面一個大於後面一個數字,則這兩個數字組成一個逆序對。請設計一個高效的算法,計算給定數組中的逆序對個數。
給定一個int數組A和它的大小n,請返回A中的逆序對個數。保證n小於等於5000。
測試樣例:
輸入:[1,2,3,4,5,6,7,0],8
返回:7
這道題如果用常規的遍歷數組,對每個元素再進行數組的遍歷,時間複雜度爲O(n),肯定會超時,下面介紹一種時間複雜度爲O(nlogn)。
/**
* 封裝的一個數據類
*/
class Node {
// 值
int value;
// 比當前節點value大的節點數
int leftSize = 0;
Node left, right;
public Node(int value) {
this.value = value;
}
/**
* 將比自己大的節點放到前面,leftSize++,比自己小的,放到自己後面
*/
public void insert(int val) {
if (val > this.value) {
if (left != null) {
left.insert(val);
} else {
left = new Node(val);
}
leftSize++;
} else {
if (right != null) {
// 調用後面的節點的排序,隨時保持leftSize的更新
right.insert(val);
} else {
right = new Node(val);
}
}
}
// 得到比自己大的節點的數量
public int getRank(int val) {
if (val == this.value) {
return leftSize;
} else if (val > this.value) {
return left.getRank(val);
} else {
return leftSize + 1 + right.getRank(val);
}
}
}
public class AntiOrder {
Node root = null;
public int count(int[] A, int n) {
int res = 0;
for (int i = 0; i < n; i++) {
res += helper(A[i]);
}
return res;
}
public int helper(int n) {
if (this.root == null) {
root = new Node(n);
return 0;
} else {
root.insert(n);
return root.getRank(n);
}
}
}