Merge k sorted linked lists and return it as one sorted list.
Analyze and describe its complexity.
Example
Given lists:
[
2->4->null,
null,
-1->null
],
return -1->2->4->null.
O(nLogk)时间复杂度。三种做法都要会。
1.维护最小堆。每个链表已经排序了,头相当于帮派最强者,每次要选出各帮派此时最强者,那只要比所有列表头即可,想到用堆。初始化把所有头扔进去,while循环堆没空,就把当前最强者当整体排序链表的下一个;检查一下刚才poll出来的下一位是不是null,不是null的话继续放到堆里。
2.分治法,自顶向下,递归。
函数private ListNode merge2List(ListNode head1, ListNode head2)负责把两条ListNode链合在一起,函数private ListNode mergeHelper(List<ListNode> lists, int start, int end)负责分别叫左右都合成一条,再把这两条合好传回去。递归出口是只有一条的时候返回自己。顶上一层层分配任务下去给两边。
3.自底向上,遍历非递归。
还是先写一个合两条的方法。每次两条两条合并,比如12345678就12,34,56,78合合,接着下一轮两两合并,直到最后只剩下一条返回。可以感受到是从底下慢慢向上只剩一条吧。不过这个方法注意写隔两个隔两个合并的部分的时候,记得for循环+=2!!别手快写错,一开始只+1死循环找错好久。
实现1: 维护最小堆。
/** * Definition for ListNode. * public class ListNode { * int val; * ListNode next; * ListNode(int val) { * this.val = val; * this.next = null; * } * } */ public class Solution { /** * @param lists: a list of ListNode * @return: The head of one sorted list. */ public ListNode mergeKLists(List<ListNode> lists) { // write your code here if (lists == null || lists.size() == 0) { return null; } int k = lists.size(); PriorityQueue<ListNode> minHeap = new PriorityQueue<>(k, new Comparator<ListNode>() { @Override public int compare(ListNode n1, ListNode n2) { return n1.val - n2.val; } }); for (int i = 0; i < k; i++) { if (lists.get(i) != null) { minHeap.offer(lists.get(i)); } } ListNode dummy = new ListNode(-1); ListNode crt = dummy; while (!minHeap.isEmpty()) { ListNode minNode = minHeap.poll(); crt.next = minNode; crt = crt.next; if (minNode.next != null) { minHeap.offer(minNode.next); } } return dummy.next; } }
实现2: 分治法,自顶向下,递归。
/** * Definition for ListNode. * public class ListNode { * int val; * ListNode next; * ListNode(int val) { * this.val = val; * this.next = null; * } * } */ public class Solution { /** * @param lists: a list of ListNode * @return: The head of one sorted list. */ public ListNode mergeKLists(List<ListNode> lists) { // write your code here if (lists == null || lists.size() == 0) { return null; } return mergeHelper(lists, 0, lists.size() - 1); } private ListNode mergeHelper(List<ListNode> lists, int start, int end) { if (start == end) { return lists.get(start); } int mid = start + (end - start) / 2; ListNode leftResult = mergeHelper(lists, start, mid); ListNode rightResult = mergeHelper(lists, mid + 1, end); return merge2List(leftResult, rightResult); } private ListNode merge2List(ListNode head1, ListNode head2) { ListNode dummy = new ListNode(-1); ListNode crt = dummy; while (head1 != null || head2 != null) { if (head2 == null) { crt.next = head1; head1 = head1.next; } else if (head1 == null) { crt.next = head2; head2 = head2.next; } else if (head1.val < head2.val) { crt.next = head1; head1 = head1.next; } else { crt.next = head2; head2 = head2.next; } crt = crt.next; } return dummy.next; } }
实现3: 自底向上,遍历非递归。
/** * Definition for ListNode. * public class ListNode { * int val; * ListNode next; * ListNode(int val) { * this.val = val; * this.next = null; * } * } */ public class Solution { /** * @param lists: a list of ListNode * @return: The head of one sorted list. */ public ListNode mergeKLists(List<ListNode> lists) { // write your code here if (lists == null || lists.size() == 0) { return null; } List<ListNode> crtLists = lists; while (crtLists.size() > 1) { List<ListNode> newLists = new ArrayList<>(); // 千万注意这里是+=2!!!不然就死循环而且逻辑错误了!!!别手快 for (int i = 0; i < crtLists.size(); i += 2) { if (i + 1 == crtLists.size()) { newLists.add(crtLists.get(i)); } else { newLists.add(merge2List(crtLists.get(i), crtLists.get(i + 1))); } } crtLists = newLists; System.out.println("1"); } return crtLists.get(0); } private ListNode merge2List(ListNode head1, ListNode head2) { ListNode dummy = new ListNode(-1); ListNode crt = dummy; while (head1 != null || head2 != null) { if (head2 == null) { crt.next = head1; head1 = head1.next; } else if (head1 == null) { crt.next = head2; head2 = head2.next; } else if (head1.val < head2.val) { crt.next = head1; head1 = head1.next; } else { crt.next = head2; head2 = head2.next; } crt = crt.next; System.out.println("2"); } return dummy.next; } }