【剑指Offer】个人学习笔记_25_合并两个排序的链表

刷题日期:20:4133 星期三2021年3月31日

个人刷题记录,代码收集,来源皆为leetcode

经过多方讨论和请教,现在打算往Java方向发力

主要答题语言为Java

题目:

剑指 Offer 25. 合并两个排序的链表

难度简单103

输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。

示例1:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

限制:

0 <= 链表长度 <= 1000
题目分析

没说链表里的数据一定是整数

又是链表题,连着三道了,集中训练啊,肯定得用指针,其次可以直接在其中一串上面进行操作,节省空间,合并链表需要注意后面的信息不能丢掉,因此可能还会需要临时指针,处理完毕后返回操作的那个链表即可。

初始解答:

尝试解答,参考了书:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        //自己一开始没有想到递归的解法,看来链表是离不开递归了
        //考虑特殊情况
        if (l1 == null) return l2;
        if (l2 == null) return l1;
        //首先定义两个指针指向两个链表的头节点,和一个作为比较的节点
        ListNode n1 = l1, n2 = l2, cur = null;
        //其次判断需要从哪个开始,相等则随意
        if (l1.val <= l2.val) {
            //l1小则从l1开始
            cur = l1;
            cur.next = mergeTwoLists(l1.next,l2);
        }
        else {
            //否则默认从l2开始
            cur = l2;
            cur.next = mergeTwoLists(l1,l2.next);
        }
        return cur;
    }
}

执行结果: 通过

显示详情

执行用时:1 ms, 在所有 Java 提交中击败了99.67%的用户

内存消耗:38.7 MB, 在所有 Java 提交中击败了26.57%的用户

自己差在了没能看到链表就想到递归,不然这个思路并不难做出来。

尝试用迭代的方法实现,想复现K神的方法:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dum = new ListNode(0), cur = dum; //伪头节点,和指针
        while (l1.next != null && l2.next != null) {
            if (l1.val < l2.val) {
                dum.next = l1;
                // dum.next = cur;
                l1 = l1.next; //前进
            }
            else {
                dum.next = l2;
                // dum.next = cur;
                l2 = l2.next;//前进
            }
            cur = cur.next; //不能缺,否则一直原地踏步
        }
        if (l1.next == null && l2.next != null) cur.next = l2;
        if (l2.next == null && l1.next != null) cur.next = l1;

        return dum.next;
    }
}

分析不出来,老是输出两个数

输入 [1,2,4] [1,3,4]

输出 [2,4]

预期结果 [1,1,2,3,4,4]

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dum = new ListNode(0), cur = dum; //伪头节点,和指针
        while (l1 != null && l2 != null) { //这里多了.next
            if (l1.val < l2.val) {
                cur.next = l1;
                // dum.next = cur;
                l1 = l1.next; //前进
            }
            else {
                cur.next = l2;
                // dum.next = cur;
                l2 = l2.next;//前进
            }
            cur = cur.next; //不能缺,否则一直原地踏步
        }
        //判断时就不应该带这么多.next,本来就已经走到链尾了,再取就错了
        // if (l1.next == null && l2.next != null) cur.next = l2;
        // if (l2.next == null && l1.next != null) cur.next = l1;
        //两句通俗实现,与下面那句一样的功能
        if (l1 != null) cur.next = l1;
        if (l2 != null) cur.next = l2;
        //一句三元表达式或者条件判断表达式写法
        // cur.next = l1 != null ? l1 : l2; //高深
        return dum.next;
    }
}

分析都在代码里了。

执行结果:通过

显示详情

执行用时:1 ms, 在所有 Java 提交中击败了99.67%的用户

内存消耗:38.6 MB, 在所有 Java 提交中击败了47.45%的用户

学习他人:

方法一:

mata川L5 2020-02-22

  1. 迭代
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummyHead = new ListNode(-1), pre = dummyHead;
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                pre.next = l1;
                pre = pre.next;
                l1 = l1.next;
            } else {
                pre.next = l2;
                pre = pre.next;
                l2 = l2.next;
            }
        }
        if (l1 != null) {
            pre.next = l1;
        }
        if (l2 != null) {
            pre.next = l2;
        }

        return dummyHead.next;
    }
}
  1. 递归
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) {
            return l2;
        }
        if (l2 == null) {
            return l1;
        }
        if (l1.val <= l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }
    }
}

方法二:

😶 (编辑过)2020-09-06

Java:

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        // 遍历两个链表,比较大小合并。
        // 申请一个伪头节点
        ListNode dum = new ListNode(0);
        ListNode cur = dum; // cur用来指向新插入的节点
        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                cur.next = l1;
                l1 = l1.next;
            }else{
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;  // cur指向刚插入进来的节点
        }
        // 若l1 == null,直接把l2后面插入进来。否则就是l2=null了。
        // 跳出循环的条件是有一个为空了。
        cur.next = l1 != null ? l1 : l2; 
        return dum.next;  // dum是空节点,新链表的头节点是dum的后一个节点
    }
}

方法三:

惯例K神,看过解释后更加明了了

作者:jyd
链接:https://leetcode-cn.com/problems/he-bing-liang-ge-pai-xu-de-lian-biao-lcof/solution/mian-shi-ti-25-he-bing-liang-ge-pai-xu-de-lian-b-2/
来源:力扣(LeetCode)

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dum = new ListNode(0), cur = dum;
        while(l1 != null && l2 != null) {
            if(l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            }
            else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        cur.next = l1 != null ? l1 : l2;
        return dum.next;
    }
}

总结

以上就是本题的内容和学习过程了,就两种解法,还是好好学习递归解法,迭代反而更复杂了,还得用到伪头节点,自己想的办法也没有尝试实现,之后再说。

欢迎讨论,共同进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值