import java.util.StringJoiner; import static util.Asserts.assertArrayEquals; import static util.Asserts.assertEquals; import static util.Asserts.assertNotNull; /** *
* 23. åå¹¶K个ååºé¾è¡¨ * * é¾åº¦ï¼å°é¾ * * ç»ä½ ä¸ä¸ªé¾è¡¨æ°ç»ï¼æ¯ä¸ªé¾è¡¨é½å·²ç»æååºæåã * * è¯·ä½ å°ææé¾è¡¨åå¹¶å°ä¸ä¸ªååºé¾è¡¨ä¸ï¼è¿ååå¹¶åçé¾è¡¨ã * * * * ç¤ºä¾ 1ï¼ * * è¾å ¥ï¼lists = [[1,4,5],[1,3,4],[2,6]] * è¾åºï¼[1,1,2,3,4,4,5,6] * è§£éï¼é¾è¡¨æ°ç»å¦ä¸ï¼ * [ * 1->4->5, * 1->3->4, * 2->6 * ] * å°å®ä»¬åå¹¶å°ä¸ä¸ªæåºé¾è¡¨ä¸å¾å°ã * 1->1->2->3->4->4->5->6 * * ç¤ºä¾ 2ï¼ * * è¾å ¥ï¼lists = [] * è¾åºï¼[] * * ç¤ºä¾ 3ï¼ * * è¾å ¥ï¼lists = [[]] * è¾åºï¼[] * * * * æç¤ºï¼ * * k == lists.length * 0 <= k <= 10^4 * 0 <= lists[i].length <= 500 * -10^4 <= lists[i][j] <= 10^4 * lists[i] æ ååº æå * lists[i].length çæ»åä¸è¶ è¿ 10^4 * * æ¥æºï¼åæ£ï¼LeetCodeï¼ * 龿¥ï¼https://leetcode.cn/problems/merge-k-sorted-lists * è使å½é¢æ£ç½ç»ææãåä¸è½¬è½½è¯·èç³»å®æ¹ææï¼éåä¸è½¬è½½è¯·æ³¨æåºå¤ã ** * @author abomb4 2022-10-12 22:21:22 */ public class Solution23 { public ListNode mergeKLists(ListNode[] lists) { if (lists.length == 0) { return null; } SmallHeap heap = new SmallHeap(32 - Integer.numberOfLeadingZeros(lists.length)); for (ListNode node : lists) { if (node != null) { heap.add(node); } } ListNode head = null; ListNode current = null; while (heap.size > 0) { final ListNode peek = heap.replaceTopNode(); if (peek == null) { break; } if (head == null) { head = peek; current = head; } else { current.next = peek; current = current.next; } } return head; } public static class SmallHeap { ListNode[] base; int size = 0; SmallHeap(int level) { // 1: root only // 2: 3 nodes base = new ListNode[(int)Math.pow(2, level) - 1]; } public void add(ListNode node) { base[size] = node; shiftUp(size); size += 1; } ListNode peek() { if (size == 0) { return null; } return base[0]; } ListNode replaceTopNode() { if (size == 0) { return null; } ListNode top = base[0]; ListNode next = top.next; if (top.next == null) { // remove top swap(0, size - 1); size -= 1; if (size > 0) { shiftDown(0); } } else { base[0] = next; if (top.val != next.val) { shiftDown(0); } } return top; } void shiftDown(int index) { int downTo = index; final int leftIndex = indexLeftChild(index); if (leftIndex < size && base[leftIndex].val < base[downTo].val) { downTo = leftIndex; } final int rightIndex = indexRightChild(index); if (rightIndex < size && base[rightIndex].val < base[downTo].val) { downTo = rightIndex; } if (downTo != index) { swap(downTo, index); shiftDown(downTo); } } void shiftUp(int index) { int parentIndex = indexParent(index); if (parentIndex == -1) { return; } int parentVal = base[parentIndex].val; int thisVal = base[index].val; if (parentVal > thisVal) { swap(parentIndex, index); shiftUp(parentIndex); } } void swap(int i1, int i2) { final ListNode tmp = base[i1]; base[i1] = base[i2]; base[i2] = tmp; } static int indexParent(int index) { return index == 0 ? -1 : (index - 1) / 2; } static int indexLeftChild(int index) { return index * 2 + 1; } static int indexRightChild(int index) { return index * 2 + 2; } } public static void main(String[] args) { final Solution23 s = new Solution23(); { String in = "[[1,4,5],[1,3,4],[2,6]]"; String expect = "[1,1,2,3,4,4,5,6]"; final ListNode result = s.mergeKLists(toNodes(in)); final String real = toString(result); assertEquals(expect, real, "in: " + in); } { String in = "[[]]"; String expect = "[]"; final ListNode result = s.mergeKLists(toNodes(in)); final String real = toString(result); assertEquals(expect, real, "in: " + in); } System.out.println("OK"); } static String toString(ListNode node) { if (node == null) { return "[]"; } final StringJoiner sb = new StringJoiner(",", "[", "]"); ListNode current = node; while (current != null) { sb.add(String.valueOf(current.val)); current = current.next; } return sb.toString(); } static ListNode[] toNodes(String in) { final String sub = in.substring(2, in.length() - 2); final String[] groups = sub.split("],\\["); final ListNode[] result = new ListNode[groups.length]; for (int i = 0; i < groups.length; i++) { String group = groups[i]; if (group == null || group.isEmpty()) { continue; } final String[] nums = group.split(","); ListNode root = null; ListNode current = null; for (String str : nums) { final int num = Integer.parseInt(str); if (root == null) { root = new ListNode(num); current = root; } else { current.next = new ListNode(num); current = current.next; } } result[i] = root; } return result; } static class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } }