模拟面试的时候没做出来,心碎了。
题目链接
. - 力扣(LeetCode)
自己的思考
无思考,直接看答案吧。
正确答案
其实写还是自己写的,看了下题解的思路。
第一种
思路简单,两两合并,注意事项已经标出。
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
// 不能写成ListNode ans = new ListNode();
//这样你对ans初始化了且值为0,多了一个值
ListNode ans = null;
for(ListNode list: lists){
ans = merge(ans, list);//返回头节点
}
return ans;
}
public ListNode merge(ListNode l1, ListNode l2){
ListNode dummy = new ListNode();
ListNode root = dummy;
if(l1 == null){
return l2;
}
if(l2 == null) return l1;
while(l2 != null && l1 != null){
if(l1.val <= l2.val){
dummy.next = l1;
l1 = l1.next;
}else{
dummy.next = l2;
l2 = l2.next;
}
dummy = dummy.next;
}
dummy.next = l1 == null ? l2 : l1;
return root.next;
}
}
第二种
这个方法和前两种方法的思路有所不同,我们需要维护当前每个链表没有被合并的元素的最前面一个,k 个链表就最多有 k 个满足这样条件的元素,每次在这些元素里面选取 val 属性最小的元素合并到答案中。在选取最小元素的时候,我们可以用优先队列来优化这个过程。
难点就是自己写优先队列的排序函数。
Comparable接口
包含compareTo定义
class Solution {
class Status implements Comparable<Status> {//自己创建堆的结点定义排序规则
int val;
ListNode ptr;
Status(int val, ListNode ptr){
this.val = val;
this.ptr = ptr;
}
public int compareTo(Status status2){
return this.val - status2.val;
}
}
PriorityQueue<Status> queue = new PriorityQueue<Status>();
public ListNode mergeKLists(ListNode[] lists) {
for(ListNode list: lists){
if(list != null){//一定要排除,因为null没有.val
//直接写指代的就是结点本身
//放入是offer
queue.offer(new Status(list.val, list));
}
}
ListNode head = new ListNode();
ListNode tail = head;
while(!queue.isEmpty()){
//离开时poll
Status f = queue.poll();
tail.next = f.ptr;
tail = tail.next;
if(f.ptr.next != null){
//放入不为空的节点
queue.offer(new Status(f.ptr.next.val, f.ptr.next));
}
}
return head.next;
}
}