题目:
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
解法1:暴力法
调用mergeTwoLists函数 依次合并
c++:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector& lists) {
int n = lists.size();
if(n == 0) return nullptr;
ListNode* ans = lists[0];
for(int i = 1; i < n; i++){
ans = mergeTwoLists(ans, lists[i]);
}
return ans;
}
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == nullptr) return l2;
if (l2 == nullptr) return l1;
ListNode dummy(-1);
ListNode* cur = &dummy;
while(l1 && l2){
if(l1->val <= l2->val){
cur->next = l1;
l1 = l1->next;
} else {
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
cur->next = (l1 != nullptr) ? l1 : l2;
return dummy.next;
}
};
解法2:
Divide and Conquer Approach(分治法)
每次将问题分为两半,然后将链表两两合并,这样问题的规模就缩小一半,重复上述过程,直至只剩一个链表
链表数奇数 为了空出中间链表 需用(n + 1) / 2而不是n / 2 例如7个链表 k = (n + 1) / 2=4 0号链表和(0+4)=4 号链表合并 1号链表和(1+4)=5 号链表合并 2号链表和(2+4)=6号链表合并 空出中间3号链表不合并 注意 合并的次数为n / 2 次
链表数偶数 (n + 1) / 2和n / 2结果一样 为了和奇数保持一致 用(n + 1) / 2 例如6个链表 k = (n + 1) / 2=3 0号链表和(0+3)=3 号链表合并 1号链表和(1+3)=4 号链表合并 2号链表和(2+3)=5号链表合并 合并的次数为n / 2 次
c++:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector& lists) {
int n = lists.size();
if(n == 0) return nullptr;
while(n > 1){
int k = (n + 1) / 2;
for(int i = 0; i < n / 2; i++){
lists[i] = mergeTwoLists(lists[i], lists[i + k]);
}
n = k;
}
return lists[0];
}
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == nullptr) return l2;
if (l2 == nullptr) return l1;
ListNode dummy(-1);
ListNode* cur = &dummy;
while(l1 && l2){
if(l1->val <= l2->val){
cur->next = l1;
l1 = l1->next;
} else {
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
cur->next = (l1 != nullptr) ? l1 : l2;
return dummy.next;
}
};
java:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int n = lists.length;
if(n == 0) return null;
while(n > 1){
int k = (n + 1) / 2;
for(int i = 0; i < n / 2; i++){
lists[i] = mergeTwoLists(lists[i], lists[i + k]);
}
n = k;
}
return lists[0];
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
while(l1 != null && l2 != null){
if(l1.val <= l2.val){
cur.next = l1;
l1 = l1.next;
} else {
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
cur.next = (l1 != null) ? l1 : l2;
return dummy.next;
}
}
Python:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
n = len(lists)
if n == 0: return None
while n > 1:
k = (n + 1) / 2
for i in range(n / 2):
lists[i] = self.mergeTwoLists(lists[i], lists[i + k])
n = k
return lists[0]
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if l1 == None: return l2
if l2 == None: return l1
dummy = ListNode(-1)
cur = dummy
while l1 != None and l2 != None:
if l1.val <= l2.val:
cur.next = l1
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur = cur.next
cur.next = l1 if (l1 != None) else l2
return dummy.next
解法3:优先级队列法
假设有三个链表
1,4,5
3,7,9
2,3,6
首先创建优先级队列,首先将所有链表的头结点入队列,即1,3,2入队,在优先级队列中自动按照大小顺序从小到达排好队 1,2,3,
建立头结点dummy和指向它的指针cur,取出优先级队列中的首个元素即1,加入目标链表,首先查看1是否有后继,如果有,将它即4加入优先级队列继续进行排列,最后直到优先级队列为空
c++:
cmp函数参数不能加引用,另外必须是a->val > b->val,表示从小到大排列,与结构体中的排序函数不同
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
struct cmp {
bool operator() (const ListNode* a, const ListNode* b){
return a->val > b->val;
}
};
class Solution {
public:
ListNode* mergeKLists(vector& lists) {
priority_queue, cmp> q;
for(auto l : lists){
if(l) q.push(l);
}
ListNode dummy(-1);
ListNode* cur = &dummy;
while(!q.empty()){
auto temp = q.top();
q.pop();
cur->next = temp;
cur = cur->next;
if(cur->next) q.push(cur->next);
}
return dummy.next;
}
};
java:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists == null || lists.length == 0) return null;
PriorityQueue q = new PriorityQueue(lists.length, new Comparator(){
@Override
public int compare(ListNode o1, ListNode o2){
return o1.val - o2.val;
}
});
for(ListNode l : lists){
if(l != null) q.add(l);
}
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
while(!q.isEmpty()){
ListNode temp = q.peek();
q.poll();
cur.next = temp;
cur = cur.next;
if(cur.next != null) q.add(cur.next);
}
return dummy.next;
}
}
Python:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
from Queue import PriorityQueue
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
n = len(lists)
q = PriorityQueue(maxsize = n)
dummy = ListNode(None)
cur = dummy
for node in lists:
if node: q.put((node.val,node))
while q.qsize() > 0:
temp = q.get()
cur.next = temp[1]
cur = cur.next
if cur.next: q.put((cur.next.val,cur.next))
return dummy.next
python3:
python3的优先级队列可能遇到不同的链表拥有相同的数值的结点会继续比较第二条件即结点,由于结点不能比较,所以报错
所以要给出第二条件 索引值idx 不同的链表的索引不同
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
from queue import PriorityQueue
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
n = len(lists)
q = PriorityQueue(maxsize = n)
dummy = ListNode(None)
cur = dummy
for idx, node in enumerate(lists):
if node: q.put((node.val,idx,node))
while q.qsize() > 0:
temp = q.get()
idx, cur.next = temp[1], temp[2]
cur = cur.next
if cur.next: q.put((cur.next.val,idx,cur.next))
return dummy.next
解法4:递归法
链表分为两段,递归的求解左半部分和右半部分,然后再用mergeTwoLists合并
c++:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector& lists) {
int n = lists.size();
return partion(lists, 0, n - 1);
}
ListNode* partion(vector& lists, int start, int end) {
if(start < end) return nullptr;
if(start == end) return lists[start];
int mid = start + (end - start) / 2;
ListNode* left = partion(lists, start, mid);
ListNode* right = partion(lists, mid + 1, end);
return mergeTwoLists(left, right);
}
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == nullptr) return l2;
if (l2 == nullptr) return l1;
ListNode dummy(-1);
ListNode* cur = &dummy;
while(l1 && l2){
if(l1->val <= l2->val){
cur->next = l1;
l1 = l1->next;
} else {
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
cur->next = (l1 != nullptr) ? l1 : l2;
return dummy.next;
}
};
java:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int n = lists.length;
return partion(lists, 0, n - 1);
}
public ListNode partion(ListNode[] lists, int start, int end) {
if(start > end) return null;
if(start == end) return lists[start];
int mid = start + (end - start) / 2;
ListNode left = partion(lists, start, mid);
ListNode right = partion(lists, mid + 1, end);
return mergeTwoLists(left, right);
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
while(l1 != null && l2 != null){
if(l1.val <= l2.val){
cur.next = l1;
l1 = l1.next;
} else {
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
cur.next = (l1 != null) ? l1 : l2;
return dummy.next;
}
}
python:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
from Queue import PriorityQueue
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
n = len(lists)
return self.partion(lists, 0, n - 1)
def partion(self, lists, start, end):
if start > end: return None
if start == end: return lists[start]
mid = start + (end - start) / 2
left = self.partion(lists, start, mid)
right = self.partion(lists, mid + 1, end)
return self.mergeTwoLists(left, right)
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if l1 == None: return l2
if l2 == None: return l1
dummy = ListNode(-1)
cur = dummy
while l1 != None and l2 != None:
if l1.val <= l2.val:
cur.next = l1
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur = cur.next
cur.next = l1 if (l1 != None) else l2
return dummy.next