目录
一. Merge Two Sorted Arrays/Lists
二. Merge K Sorted Arrays/Lists
一. Merge Two Sorted Arrays/Lists
- Leetcode #88. Merge Sorted Array
- Leetcode #21. Merge Two Sorted Lists
给两个sorted arrays A and B,有两种问法:
1. 返回一个新的数组C,大小是A.length + B.length
- 做法:每次比较A.head和B.head,谁小谁出列,放到C中;直到A或B为空,把剩下那个非空的全部加进去。
- Merge Lists的思路与这种解法相同,但要注意的是,Merge List本质上是重构了链表,修改了next指针,并没有new一个新的链表出来。
- 复杂度:O(m+n)
2. 假设A数组空间足够大,全部in-place的合并到A数组
- 做法:因为A数组是「前一部分有数,后一部分空闲」的结构,所以我们可以从大到小合并。每次比较A.tail和B.tail,谁大谁放到最后的空位上。这么做是为了避免因为B中元素要插入到index i的位置,A中原本index i之后的元素需要整体后移的情况,如A=[3,4,5],B=[1,2],每次3,4,5都要整体后移,最坏情况下这种移动要花O(nm)的时间
- 复杂度:O(m+n)
二. Merge K Sorted Arrays/Lists
- Leetcode #23. Merge k Sorted Lists
解法1. Heap(PriorityQueue)
参考merge two的思想,很容易想到的做法就是每次把k个链表的head拿来比较。最小的出列。而在k个元素中快速找到最小值,我们首先想到的数据结构就是堆(Heap/PriorityQueue)。
时间复杂度:O(N*logK)
Initialization(The firts for loop): O(N)
while循环:每个ListNode都会被访问一次,所以while循环会循环N次(N为K个链表的全部节点个数),而每个while循环内,heap.poll()花费O(1),heap.offer()花费O(K)(因为heap的大小是K,heap的增删操作都是O(size of heap))。
解法2.分治法
有时候面试官会不让用Heap,这时候我们可以从Brute force出发,看有没有什么可优化的地方。
看一下时间复杂度和K的关系:
K=1时, 不用排,直接返回 --> O(1)
K=2时,相当于merge two --> O(N)
...
K = N时,相当于每个链表只有一个节点,我们需要对N个节点进行排序 --> O(NlogN)
所以我们猜测,时间复杂度是O(NlogK)。这就暗示了我们需要够一个logK高度的递归,每次递归花费O(N)。而logK高度的递归,自然想到每次把K的大小砍一半。
解法3.两两合并
另一种不让用Heap时的想法,过程为:先合并list 1&2,3&4,...,k-1&k,再把1&2的结果和3&4的结果合并....如此循环,直到最后只剩下一个list,返回。
时间复杂度:每个节点最多参与logK次合并,共N个节点,所以时间复杂度依旧为O(NlogK)。
三. Merge Interval Lists
- Leetcode #56. Merge Intervals
- Lintcode #839 · Merge Two Sorted Interval Lists
- Lintcode #577. Merge K Sorted Interval Lists
Interval之间合并的规则是:后一个interval的stat要<=前一个 interva的end才能合并。合并后新的interval的end是两个interval的end的最大值。eg:
interval1: start1|_________|end1
interval2: start2|______|end2 --> (start1 ~ end2)
interval1: start1|_________|end1
interval2: start2|__|end2 --> (start1 ~ end1)
interval1: start1|_________|end1
interval2: start2|______|end2 --> 不能合并
Merge interval其实和merge整数的思路一模一样,只有一点不同:
每次出列的”最小的“interval不能直接放到结果集中输出,要看它能不能被其他interval合并。所以我们可以写一个函数,将每次出列的interval正确的放到result中:
只要把以上Merge Arrays/Lists的代码中的result.add(head)改成pushBack(result, head)即可。