**题目:**Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze
and describe its complexity.
分析:题意要求将k个排好序的链表,整合为一个排好序链表,该题是之前的合并两个排好序的链表的延伸,延伸为一般情况。基本思想与两链表合并一样,可参见之前的博客。
第一种方法:递归思想,依次两两合并为一个链表,直到合并为一个链表,此处两种思路:
1>从数组遍历开始,相邻的元素两两合并,合并后的链表直接赋值给相邻元素id大那个元素,重复上述过程!如下图示:
![]()
该方法会出现超时问题,在对时间复杂度要求不高的情况下,可以考虑。
Java NotPass 代码:
//First method: not accept Time Limited Out
public static ListNode mergerKSortedList(ListNode[] lists) {
ListNode listNode = new ListNode(0);
mergerTwoSortedList(listNode, lists.length, lists);
return listNode.next;
}
public static void mergerTwoSortedList(ListNode listNode, int length,
ListNode[] lists) {
ListNode p;
ListNode q;
ListNode fakeHead;
if(length == 1 || length == 0){
return;
}else{
fakeHead = listNode;
p = lists[0];
q = lists[1];
while (p != null && q != null) {
if (p.val <= q.val) {
fakeHead.next = p;
p = p.next;
} else {
fakeHead.next = q;
q = q.next;
}
fakeHead = fakeHead.next;
}
if (p == null) {
fakeHead.next = q;
} else if(q == null) {
fakeHead.next = p;
}
lists[1] = listNode.next;
ListNode[] list = new ListNode[length - 1];
for (int i = 0; i < length - 1; i++) {
list[i] = lists[i + 1];
}
mergerTwoSortedList(listNode, list.length, list);
}
}
2>基于1>中的思想,考虑用二分法实现俩俩合并,时间复杂度是O(N log K)。如下图示:
Java Accepted 代码:
public class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length == 0){
return null;
}
return mergerKSortedList(lists, 0,lists.length - 1);
}
public static ListNode mergerKSortedList(ListNode[] lists,int left,int right){
if(left < right){
int mid = (left + right) / 2;
return mergerTwoSortedList(mergerKSortedList(lists, left, mid),mergerKSortedList(lists, mid + 1,right));
}
return lists[left];
}
public static ListNode mergerTwoSortedList(ListNode listNode1,ListNode listNode2) {
ListNode p;
ListNode q;
ListNode fakeHead;
ListNode head = new ListNode(0);
fakeHead = head;
p = listNode1;
q = listNode2;
while (p != null && q != null) {
if (p.val <= q.val) {
fakeHead.next = p;
p = p.next;
} else {
fakeHead.next = q;
q = q.next;
}
fakeHead = fakeHead.next;
}
if (p == null) {
fakeHead.next = q;
} else if(q == null) {
fakeHead.next = p;
}
return head.next;
}
前提:什么是优先队列: 优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。
PriorityQueue是从JDK1.5开始提供的新的数据结构接口。
如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列。
具体可见Oracle官网介绍:
http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html
第二种方法:利用优先队列即java自带的PriorityQueue类,该方法最简单直接解决问题,首先将n个链表头节点按指定大小(改写Comparator方法,该方法决定压栈的顺序)压入栈,然后取出栈顶元素,存放到目标链表上,接着再将该节点的下一个元素压入栈,直到所有链表都遍历完成。
Java Accepted 代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode mergeKLists(ListNode[] lists) {
//Special case
if(lists.length == 0 || lists == null){
return null;
}
Comparator<ListNode> order = new Comparator<ListNode>() {
public int compare(ListNode o1, ListNode o2) {
// TODO Auto-generated method stub
return o1.val - o2.val;
}
};
PriorityQueue<ListNode> p = new PriorityQueue<ListNode>(lists.length,order);
//New queue in special order
for(ListNode list: lists){
if(list != null)
p.add(list);
}
ListNode head = new ListNode(-1);
ListNode q = head;
while(!p.isEmpty()){
//Retrieves and remove the head of queue
ListNode item = p.poll();
q.next = item;
//Keep add the next node of item till item is null
if(item.next != null)
p.add(item.next);
q = q.next;
}
return head.next;
}
}
相关代码放在个人github:https://github.com/gannyee/LeetCode/