Question:
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
【合并K个排序的链表并且返回一个排序的列表。分析并描述其复杂性。】
一个链表数组,里面存放着n个链表,每个链表有若干个结点并且链表结点是顺序存储(数字从小到大)的,你需要把他们合成一个链表,并且要求链表保持从小到大的顺序不变。
分析描述问题的复杂性。
结点类
public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
Answer:
数据结构–链表;
数据结构书上讲过多链表合一的情况,当时讲的解决方案是遍历每个链表,找到最小的值后添加到新的链表中去,然后结点后移,继续寻找,直到每个链表都为空。构成的新链表就是最终链表。
public ListNode margeKLists(ListNode[] lists){
//链表长度为 0 时返回空,为 1 时返回当前链表
if(lists.length==0){
return null;
}else if(lists.length==1){
return lists[0];
}
int len = lists.length;
int min = Integer.MAX_VALUE;
int index = 0;
boolean isEmpty;
ListNode head;
ListNode node = new ListNode(Integer.MAX_VALUE);
node.next = null;
head = node;
while(node != null){
isEmpty = true;
min = Integer.MAX_VALUE;
//找出链表最小值 min 和对应的索引 index
for(int i=0; i<len; i++){
if(lists[i]!=null && min > lists[i].val){
min = lists[i].val;
index = i;
isEmpty = false;
}
}
if(isEmpty == true){
break;
}
ListNode newNode = new ListNode(min);
newNode.next = null;
node.next = newNode;
node = node.next;
lists[index] = lists[index].next;
}
head = head.next;
//ListNode p = head;
// while(p!=null){
// System.out.printf("%d ", p.val);
// p = p.next;
//}
return head;
}
因为这种方法是通过指针一个一个寻找合适的结点,相当于把整个链表数组遍历了一遍,中间还有许多比较操作,我们知道链表的查找效率是比较低的,但是他的插入和删除操作效率是比较高的,所以这种方式并不是一种好的解决方案。
另一种方案:
我们知道链表的插入和删除效率较高,查找效率低,那么我们可以避免链表的查找操作,这样便可以提升程序的速度。首先我们可以用一个数组来接收整个Lists链表数组中的所有链表的所有结点,然后再对整个数组进行排序,再将排完序后的数组组成一个链表返回,在数组中排序的速度肯定会比链表中排序速度快,同时把链表复制到数组中的时候是在对链表进行遍历操作,而最后的整合也是一个对链表的插入操作,因此时间效率会比上一种方法快很多(但是没有用到链表本身已经排好序的条件,所以一定还会有更好的解决方案,我还没想出来。。)
public ListNode margeKLists(ListNode[] lists){
ListNode xh;
List<Integer> list = new ArrayList<Integer>();
for(int i=0; i<lists.length; i++){
xh = lists[i];
while(xh != null){
list.add(xh.val);
xh = xh.next;
}
}
Collections.sort(list);
ListNode head ;
ListNode first = new ListNode(-1);
head = first;
for(int i=0; i<list.size(); i++){
ListNode nxt = new ListNode(list.get(i));
nxt.next = null;
first.next = nxt;
first = nxt;
}
// while (head.next != null){
// System.out.printf("%d ", head.next.val);
// head = head.next;
// }
return head.next;
}