前言
本篇会记录所有关于我对合并链表系列题目的题解,不定期更新
开始
LeetCode 21. 合并两个有序列表
合并链表系列,应该从LeetCode 21. 合并两个有序链表开始说起:
这道题需要掌握链表的基础遍历,通常,我们使用while循环遍历:
while(l1!=null){
// 输出链表节点值
System.out.println(l1.val);
l1 = l1.next;
}
要合并两个有序,长短不一的链表,我们可以先用while循环统一遍历,直到一条链表被遍历完:
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
// res指向一个占位节点
ListNode res = new ListNode(0);
// cur指针用来顺序指向新构建的链表的各个节点
ListNode cur = res;
// 同时遍历两条链表
while(l1!=null && l2!=null){
// 比较两个链表节点值的大小
// 较小的节点值赋予新节点并连接到res链表上
if(l1.val <= l2.val){
cur.next = new ListNode(l1.val);
l1 = l1.next;
}else{
cur.next = new ListNode(l2.val);
l2 = l2.next;
}
cur = cur.next;
}
// 此时,l1或l2为空
// 用res连接至多一个非空节点余下的链表
// 直接连接剩下的链表
if(l1!=null){
cur.next = l1;
}else{
cur.next = l2;
}
// 返回占位节点的下一个节点
return res.next;
}
}
进阶
掌握了基本的链表合并,我们可以去尝试解决别的问题啦~
LeetCode 2. 两数相加
传送门
这道题中,两个链表的对应位置的数相加后若为两位数,需要向其下一个节点进一位,我们试着用合并链表来解决:
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode res = new ListNode(0);
ListNode cur = res;
// 遍历两条链表,相加后置入新链表中
while (l1 != null && l2 != null) {
// 创建新节点,值为l1,l2两条链表对应节点值的和
cur.next = new ListNode(l1.val+l2.val);
l1 = l1.next;
l2 = l2.next;
cur = cur.next;
}
// 没遍历完的链表加到新链表尾
if(l2 != null){
cur.next = l2;
}
if(l1 != null){
cur.next = l1;
}
// ...未完
将我们的合并链表写出来后,我们对合并出来的链表进行处理:
// cur指针重置
cur = res.next;
// 对新链表中的两位数进位
while(cur!=null){
if(cur.val>9){
cur.val-=10;
// 当前面没节点时,创建新节点进位
if(cur.next!=null){
cur.next.val+=1;
}else{
cur.next = new ListNode(1);
}
}
cur = cur.next;
}
return res.next;
}
}
依次对我们合并的链表的每个节点进行遍历,每当遍历到大于等于10的节点,就执行进位操作(自身减10,往下个节点+1,没有下一个节点就新建一个值为1的节点)
LeetCode 23. 合并k个升序链表
这道题标记为困难,但其实也不难,我们已经掌握了合并链表的操作,合并k个链表就是在这个前提上递归罢了
// 创建一个递归方法,用参数n来遍历数组
public void merge(ListNode[] lists,int n){
// 当数组遍历完时,返回
if(n == lists.length){
return;
}
// 获取要合并的两条链表的头节点
ListNode cur1 = lists[0];
ListNode cur2 = lists[n];
// 定义合并后的链表
ListNode res = new ListNode(0);
ListNode cur3 = res;
// 链表合并基操
while(cur1!=null && cur2!=null){
if(cur1.val<=cur2.val){
cur3.next = new ListNode(cur1.val);
cur1 = cur1.next;
}else{
cur3.next = new ListNode(cur2.val);
cur2 = cur2.next;
}
cur3 = cur3.next;
}
if(cur1!=null){
cur3.next = cur1;
}
if(cur2!=null){
cur3.next = cur2;
}
// 将lists[0]指向合并后的链表
lists[0] = res.next;
// n+1,递归
merge(lists,n+1);
}
为了方便,我们将所有的链表合并到lists数组的第一条链表lists[0]
上
// 题目所给的主方法,参数入口
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length == 0){
return null;
}
merge(lists,1);
return lists[0];
}
在主方法中,我们只需要进行判空,并调用merge方法,然后返回lists数组的第一条链表即可~