1. 程式人生 > 其它 >java 合併 k 個已排序的連結串列

java 合併 k 個已排序的連結串列

技術標籤:連結串列java

牛客題目連結

1. 題目考點

  1. 歸併排序
  2. merge 函式三種形式
  3. PriorityQueue

2. 考點解析

  1. 使用 ArrayList,排序再插入 (投機取巧,面試千萬不可)
public ListNode mergeKLists(ArrayList<ListNode> lists) {
    ArrayList<Integer> arr = new ArrayList<>();
    
    for (int i = 0 ; i < lists.size(); i++) {
        ListNode p =
lists.get(i); while (p != null) { arr.add(p.val); p = p.next; } } arr.sort((a,b)-> a-b); ListNode dummy = new ListNode(0), r = dummy; for (int i = 0; i < arr.size(); i++) { ListNode node = new ListNode(arr.get(i)); r.
next = node; r = node; } r.next = null; return dummy.next; }
  1. 使用小頂堆 PriorityQueue,其實類似第一種方式 (面試可行)
public ListNode mergeKLists(ArrayList<ListNode> lists) {
    if (lists == null || lists.size() == 0) return null;
    
    Queue<Integer> pq  = new PriorityQueue
<>(); for (ListNode node : lists) { while (node != null) { pq.offer(node.val); node = node.next; } } ListNode dummy = new ListNode(0); ListNode r = dummy; while (!pq.isEmpty()) { ListNode node = new ListNode(pq.poll()); r.next = node; r = node; } return dummy.next; }
  1. 歸併排序,先遞迴劃分,在兩兩合併
public ListNode mergeKLists(ArrayList<ListNode> lists) {
    if (lists.size() == 0) return null;
    return mergeSort(lists, 0, lists.size() - 1);
}

public ListNode mergeSort(ArrayList<ListNode> lists, int l, int r) {
    if (l == r) return lists.get(l);
    int mid = l + ((r - l) >> 2);
    ListNode l1 = mergeSort(lists, l, mid);
    ListNode l2 = mergeSort(lists, mid + 1, r);
    return merge(l1, l2);
}
// 合併方式有三種,此處採用第一種 while (true) 的方式
public ListNode merge(ListNode l1, ListNode l2) {
    ListNode dummy = new ListNode(0);
    ListNode r = dummy;
    while (true) {
        if (l1 == null) {
            r.next = l2;
            break;
        } else if (l2 == null) {
            r.next = l1;
            break;
        } else if (l1.val < l2.val) {
            r.next = l1;
            l1 = l1.next;
            r = r.next;
        } else {
            r.next = l2;
            l2 = l2.next;
            r = r.next;
        }
    }
    return dummy.next;
}
  1. merge 函式採用一般方式
public ListNode merge(ListNode l1, ListNode l2) {
    ListNode dummy = new ListNode(0);
    ListNode r = dummy;
    while (l1 != null && l2 != null) {
        if (l1.val < l2.val) {
            r.next = l1;
            l1 = l1.next;
        } else {
            r.next = l2;
            l2 = l2.next;
        }
        r = r.next;
    }
    if (l1 !=  null) r.next = l1;
    if (l2 !=  null) r.next = l2;
    return dummy.next;
}
  1. merge 函式採用遞迴方式(不容易想到,本質是修改鏈)
public ListNode merge(ListNode l1, ListNode l2) {
    if (l1 == null) return l2;
    if (l2 == null) return l1;
     
    if (l1.val < l2.val) {
        l1.next = merge(l1.next, l2);
        return l1;
    }
    else {
        l2.next = merge(l1, l2.next);
        return l2;
    }
}