手撕面试题算法<链表> (1)——链表合并系列

这篇博客详细探讨了如何解决LeetCode中的链表合并题目,从21. 合并两个有序列表开始,通过进阶到2. 两数相加,再到23. 合并k个升序链表,讲解了链表遍历、进位操作和递归合并等技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

本篇会记录所有关于我对合并链表系列题目的题解,不定期更新

开始

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数组的第一条链表即可~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值