今天翻閱《Labuladuo的演算法小抄》時發現在使用優先佇列的PriorityQueue解決一道hard題時(leetCode 23),出現瞭如下程式碼:
ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0) return null;
// 虛擬頭結點
ListNode dummy = new ListNode(-1);
ListNode p = dummy;
// 優先順序佇列,最小堆
PriorityQueue<ListNode> pq = new PriorityQueue<>(
lists.length, (a, b)->(a.val - b.val));
// 將 k 個連結串列的頭結點加入最小堆
for (ListNode head : lists) {
if (head != null)
pq.add(head);
} while (!pq.isEmpty()) {
// 獲取最小節點,接到結果連結串列中
ListNode node = pq.poll();
p.next = node;
if (node.next != null) {
pq.add(node.next);
}
// p 指標不斷前進
p = p.next;
}
return dummy.next;
}
程式碼中出現了 PriorityQueue<ListNode> pq = new PriorityQueue<>(lists.length, (a, b)->(a.val - b.val));
而在檢視PriorityQueue原始碼時:
看到PriorityQueue的初始化引數其實是Comparator,也就是在書上的程式碼在此處使用了Lambda代替了Comparator.
但為什麼可以這樣處理呢?在查詢原始碼後我發現了,最終在最小堆中的比較會對映到siftUpUsingComparator中的Comparator.compare(x,(E)e):
也就是說我們在插入節點,建堆時使用的比較就是Comparator.compare(),而底層已經默認了使用正負來比較大小。因此使用Lambda方法將(a,b)作為引數返回a.val-b.val 用來代替compare方法是可行的。