博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(python版) Leetcode-21.合并两个有序链表 merge-two-sorted-lists
阅读量:4091 次
发布时间:2019-05-25

本文共 2336 字,大约阅读时间需要 7 分钟。

01 题目

链接:https://leetcode-cn.com/problems/merge-two-sorted-lists

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例

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

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

02 解析&代码1【递归法】

终止条件:当两个链表都为空时,表示我们对链表已合并完成。

如何递归:我们判断 l1 和 l2 头结点哪个更小,然后较小结点的 next 指针指向其余结点的合并结果。(调用递归)
在这里插入图片描述
在这里插入图片描述
这是两张示意图(),uh 虽然例子不是题目中的,代码里也没有用新res链表存放,大概思想是这样,仅供参考。。。

class Solution:    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:        if not l1: return l2  # 终止条件,直到两个链表都空        if not l2: return l1        if l1.val <= l2.val:  # 递归调用            l1.next = self.mergeTwoLists(l1.next,l2)            return l1        else:            l2.next = self.mergeTwoLists(l1,l2.next)            return l2

四行代码的递归

class Solution:    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:        if l1 and l2:            if l1.val > l2.val: l1, l2 = l2, l1            l1.next = self.mergeTwoLists(l1.next, l2)        return l1 or l2

关于return中的or,作用如下:

若l1或者l2中 都为空,返回None;若有一个为空(或先被用完),返回另一个;

or 的运算规则:0|0=0;0|1=1;1|0=1;1|1=1;

即:参加运算的两个对象只要有一个为1,其值为1

03 解析&代码2【迭代法】哑结点

总结的链表题目套路

  • 哑节点

    创建 哑节点 作为 结果链表 的开头,返回结果是这个节点的下一个位置。
    目的是:在未遍历之前,我们不知道构建的结果中,开头元素到底是 l1 还是 l2, 为了让代码整齐,创建哑节点。

  • 使用 move 游标

    哑节点标记了 结果链表 的开头,因此是不能移动的。为了把两个链表 merge 的结果放到结果链表的最后,就需要使用一个 move 游标指向 结果链表 的最后一个元素。初始时,move 指向 哑节点,之后随着结果链表的增加而不停地向后移动,始终保持其指向 结果链表 的最后一个元素。

  • while 遍历两个元素

    涉及到两个元素的遍历题,使用 while l1 and/or l2 的方式。即两个元素都没有遍历完或者至少有一个没遍历完,具体使用 and 还是 or 要根据场景进行选择。

    这类常见的题目有:

    合并两个链表  两数相加/两个链表表示的数相加
  • 没用完的元素仍需拼接

    当 while 循环结束之后,l1 和 l2 至少遍历完了一个,另一个链表可能没有用完,因此需要拼接到 结果链表 的结尾。
    合并链表 或者 两数相加 都要记得这个问题。

至于本题并不难,只需要判断两个链表头部元素的大小,把小的那个链表节点放到 结果链表 的结尾即可。

然而我第一时间想到的是先比较哪个链表更长。。。多此一举

class Solution:    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:        # 创建哑节点作为 结果链表 的开头        dummy = ListNode(0)        # 有个游标,标识 结果链表 的结尾        move = dummy        # l1 和 l2 都未遍历结束        while l1 and l2:            # 如果 l1 的数值比较小            if l1.val <= l2.val:                # 把 l1 头部节点拼接到 结果链表 的结尾                move.next = l1                # l1 指向下一个节点                l1 = l1.next            else:                # 把 l2 头部节点拼接到 结果链表 的结尾                move.next = l2                # l2 指向下一个节点                l2 = l2.next            # 移动 结果链表 的结尾指针            move = move.next        # l1 或者 l2 尚未使用完,拼接到 结果链表 的最后        move.next = l1 if l1 else l2        # 返回哑节点的下一个位置        return dummy.next

转载地址:http://sujii.baihongyu.com/

你可能感兴趣的文章
JavaScript:时间日期格式验证大全
查看>>
pinyin4j:拼音与汉字的转换实例
查看>>
XML工具代码:SAX从String字符串XML内获取指定节点或属性的值
查看>>
时间日期:获取两个日期相差几天
查看>>
责任链模式 Chain of Responsibility
查看>>
高并发与大数据解决方案概述
查看>>
解决SimpleDateFormat线程安全问题NumberFormatException: multiple points
查看>>
MySQL数据库存储引擎简介
查看>>
处理Maven本地仓库.lastUpdated文件
查看>>
Kafka | 请求是怎么被处理的?
查看>>
Java并发编程1-线程池
查看>>
CentOS7,玩转samba服务,基于身份验证的共享
查看>>
计算机网络-网络协议模型
查看>>
计算机网络-OSI各层概述
查看>>
Java--String/StringBuffer/StringBuilder区别
查看>>
mySQL--深入理解事务隔离级别
查看>>
分布式之redis复习精讲
查看>>
数据结构与算法7-栈
查看>>
线性数据结构学习笔记
查看>>
数据结构与算法14-跳表
查看>>