2.<tag-链表和归并, 优先队列>lt.21-合并两个有序链表 + lt.23-合并k个升序链表 dbc
lt.21-合并两个有序链表
[案例需求]
[思路分析一, 迭代法]
结合归并排序中的sort方法, 即可写出这道简单题
两条链表list1, list2, 在两者均未遍历到null时, 相互比较, 符合要求的加入到新链表中.
[代码实现]
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
//合并两个有序链表
/**
剪枝:
list1 == null && list2 == null return 任意
list1 == null || list2 == null 分别返回
比较大小
list1.val < list2 list1加入新链表, list1的temp后移
= 均加入, 均后移
> list2 加入, 后移.
*/
if(list1 == null && list2 == null) return null;
if(list1 == null) return list2;
if(list2 == null) return list1;
ListNode temp1 = list1;
ListNode temp2 = list2;
ListNode dummyNode = new ListNode(-1);
ListNode temp = dummyNode;
while(temp1 != null && temp2 != null){
if(temp1.val <= temp2.val){
temp.next = temp1;
temp1 = temp1.next;
temp = temp.next;
}else{
temp.next = temp2;
temp = temp.next;
temp2 = temp2.next;
}
}
if(temp1 != null)temp.next = temp1;
if(temp2 != null)temp.next = temp2;
return dummyNode.next;
}
}
[思路分析二, 递归法]
[代码实现]
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
//1.递归函数: 合并两个节点(list1和list2节点进行合并,)
//返回值: 当前遍历处的头结点
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
//2. 递归出口
if(list1 == null || list2 == null){
return list1 == null ? list2 : list1;
}
//3. 单层递归逻辑
//此时list1和list2均不为空
//我们判断 l1 和 l2 头结点哪个更小,然后较小结点的 next 指针指向其余结点的合并结果。
if(list1.val <= list2.val){
list1.next = mergeTwoLists(list1.next, list2);
return list1; // 返回给上一层的是更新后的头结点
}else{
list2.next = mergeTwoLists(list1, list2.next);
return list2;// 返回给上一层的是更新后的头结点
}
}
}
lt.23-合并k个升序链表[hard]
[案例需求]
[思路分析]
- 对于本题, 我们希望能够有一种数据结构, 把lists中的k条链表遍历后, 存入到其中, 在其中能够实现结点val之间的升序排列, 然后对这个数据结构遍历, 用next域把各个结点串起来即可, 想来想去, 最符合的就是优先队列(PriorityQueue)了, 它是一种基于堆(默认小顶堆)实现的数据结构.
- 使用优先队列的解法步骤如下:
0. 定义优先队列, 根据我们的需要传入比较器参数, new一个comparator, 重写他的compare方法让他能够按照我们想要的方式进行排序- 遍历lists, 把遍历到的每个节点添加到priorityQueue中.
- 上一步骤完成后, 遍历priorityQueue, 并用一个指向头结点dummyNode的指针p把他们串起来, 返回头结点即可.
[代码实现]
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
//1. 优先队列, 排序后存入,然后遍历优先队列处的节点都是有序的了, 我们直接连接起来即可
if(lists == null || lists.length == 0)return null;
PriorityQueue<ListNode> queue = new PriorityQueue(lists.length,
new Comparator<ListNode>(){
public int compare(ListNode r1, ListNode r2){
return r1.val - r2.val;
}
});
//2. 遍历链表节点数组
for(ListNode node : lists){
if(node != null)queue.add(node); // 注意, 这里每次存的只是数组中每条链表的头结点
//为什么如此呢? 因为给定的k条链表都是升序的, 我们先存入头结点, 后面从队列中取出时边取边存即可
// System.out.println(node.val);
}
//3. 遍历queue, 链接链表
ListNode dummy = new ListNode(-1);
ListNode temp = dummy;
while(!queue.isEmpty()){
temp.next = queue.poll(); //取出每条链表的头结点
temp = temp.next; // 往后遍历;
if(temp.next != null)queue.add(temp.next);//一边取出排好序的节点, 一边把这个节点后面的一个节点存入队列
}
return dummy.next;
}
}
[思路分析二, 分治法]
待补充
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)