当前位置: 首页 > news >正文

小木的算法日记——合成两个有序链表

接下来我们从本质上对这道题目进行一个拆解

                                                                                                                                                                                                                                                                                                                                                          

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

提示:

  • 两个链表的节点数目范围是 [0, 50]
  • -100 <= Node.val <= 100
  • l1 和 l2 均按 非递减顺序 排列

题目来源:力扣 21. 合并两个有序链表。

# 函数签名如下
def mergeTwoLists(l1: ListNode, l2: ListNode) -> ListNode:

解法

class Solution:def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:# 虚拟头结点dummy = ListNode(-1)p = dummyp1 = l1p2 = l2while p1 is not None and p2 is not None: # 比较 p1 和 p2 两个指针# 将值较小的的节点接到 p 指针if p1.val > p2.val:p.next = p2p2 = p2.nextelse:p.next = p1p1 = p1.next# p 指针不断前进p = p.nextif p1 is not None:p.next = p1if p2 is not None:p.next = p2return dummy.next

我们先讲解开头的两行代码

class Solution:def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:1 为什么我们在LEETCODE以及算法比赛中总会看待class Solution呢?  
我们可以把其看作是答题卡证明,也就是class Solution:冒号之后的是答题卡区域,你需要把你的代码写到之后的区域,机器才能识别,面试官才能识别。但如果是在你自己的项目平时的草稿算法则不需要。class Solution 就是告诉你,这是考试,其之后的区域是答题卡在其中写代码才算数,才给分,其他区域不算数。2 为什么大多数时候leetcode会在开始的时候给一个函数呢?因为Leetcode要用统一的格式来自动测试你的代码。所以要统一函数,从而让机器自动批改。def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:self 代表一个实例对象也就是——我自己  你只要记住self代表我自己就欧克了。
何时会用到self??
在class类里面,函数的第一个参数必须是self。
类外面的话(或者没有类)则有或没有self都可以
LeetCode算法中的self是固定格式,你可以将其看做是占位符,不用特意处理。我自己class 游戏角色:def 自我介绍(self):print(f"我的名字是{self.名字},我的等级是{self.等级}")def 升级(self):self.等级 += 1  # 提升“我自己”的等级self就相当于我自己,存储着我的名字,等级等信息。——————通过 self.属性名 来读取或修改当前对象的属性。l1:ListNode 的意思是说明l1的类型是链表
-> ListNode: 代表最后输出的是一个链表

class Solution:def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:# 虚拟头结点dummy = ListNode(-1)  这里定义一个虚拟头节点,让其等于-1,这个值不重要,因为虚拟,所以值取几都欧克。重要的是它起到了一个暂时带头的作用(班级牌),从而简洁了代码,如果没有它,你还得判定到底谁做头。p = dummy  这里不是将dummy赋值给P 而是让p指针的位置移动到dummy节点上!!!p1 = l1  同理,让p1移动到l1链表的头部那里p2 = l2 同理while p1 is not None and p2 is not None: # 比较 p1 和 p2 两个指针# 将值较小的的节点接到 p 指针if p1.val > p2.val:   当p1指针所指的节点对应的值大于p2时,让在虚拟节点的那个指针p与p2刚才对的那个节点链接,然后让p2指针移动到l2链表的下一个节点继续进行比较。p.next = p2p2 = p2.nextelse:p.next = p1p1 = p1.next前面几行代码,p.next=p2是挂车厢也就是把p2对应的节点先高到虚拟节点之后(虚拟系欸但那的右指针),然后p2往后移。而p指针是不动的只是挂了一个原先是l2的第一个车厢,之后的p=p.next(p指针(朝向上))才是让p指针移动的原因。# p 指针不断前进p = p.next  关于执行if/else执行完成后就会执行p=p.next,因为其缩进相同,所以肯定会一个接一个执行。而以下这两行代码与while缩进一样,意思是执行完while后,执行它们两个,注意while的条件是p1与p2同时存在,且不为空,如果p2的节点大于p1呢?两者的节点数不相等呢?那如何对剩余的元素排序?下面两行代码解决了这个问题。
如果p1还有,则放在p2if p1 is not None:p.next = p1if p2 is not None:p.next = p2你这里可能会问,p.next=p1不是只是把p1所对应的那个节点接入后面了,为什么没有p=p.next移动节点,从而继续接入呢?这里有一个小知识点,就是p.next如果在循环之外(while for)则其p1就可以代笔着整个链表,p.next=p1就直接链接整个链表了。return dummy.next
最后返回虚拟节点之后的内容就是重新排序之后的内容。

AI:

相关文章:

  • 系统思考:救火先放火
  • 优化通义大模型推理性能:企业级场景下的延迟与成本削减策略
  • 桌面小屏幕实战课程:DesktopScreen 3 Git工具使用
  • 21.安卓逆向2-frida hook技术-HookOkHttp的拦截器
  • 数智管理学(二十四)
  • C++ -- AVL树的插入和旋转
  • Linux 线程调度管理函数
  • leetcode:21. 合并两个有序链表
  • 华为云Flexus+DeepSeek征文|基于Dify构建解析网页写入Notion笔记工作流
  • 【C++】C++枚举、const、static的用法
  • LLM存储优化:大量长对话解决方案
  • C++ - 标准库之 <string> npos(npos 概述、npos 的作用)
  • 开发云数据库
  • 数据库索引结构 B 树、B + 树与哈希索引在不同数据查询场景下的适用性分析
  • 深入剖析Flink内存管理:架构、调优与实战指南
  • 透视618:头部主播隐退、购物氛围变淡,新秩序正在建立
  • AAudio:Android 低延迟音频处理的核心组件
  • 基于SpringBoot的RestTemplate
  • Linux——6.检测磁盘空间、处理数据文件
  • Docker Desktop + Kubernetes 使用 hostPath 持久化挂载“坑点”全解析
  • 响应式潍坊网站建设/培训心得总结
  • html5网站赏析/关键词排名怎样
  • 热点链接到另一个网站怎么做/怎么优化网站性能
  • 如何做文档附网站/免费产品推广网站
  • 富源县建设局的网站是什么/seo搜索引擎优化课程
  • 怎么用flash做游戏下载网站/谷歌下载