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

leetcode 21. 合并两个有序链表(c++解法+相关知识点复习)

目录

题目

所需知识点复习

1.链表

1.1单链表

1.2哑结点(Dummy Node)

解答过程

1.循环+双指针解法

2.递归解法


2025.4.29想到其他知识点会后续再继续补充。

题目

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

示例 1:

输入: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 均按 非递减顺序 排列

所需知识点复习

1.链表

链表(Linked List)是一种线性数据结构,由一系列的节点(Node)组成,每个节点包含:

1.数据域(val):存储数据

2.指针域(next):指向下一个节点

与数组不同,链表的内存不是连续存储的,而是通过指针连接各个节点。

1.1单链表

  • 每个节点包含val和next指针

  • 只能单向遍历(从头到尾)

  • 代码示例
  • struct ListNode {int val;ListNode *next;ListNode(int x) : val(x), next(nullptr) {}
    };
  • 判断链表是否为空:list1==nullptr

  • 在 C++ 中运算符的使用:

    • 当变量是对象实例时(如 ListNode dummy),使用 . 运算符访问成员(如 dummy.next
    • 当变量是指向对象的指针时(如 ListNode* l1),使用 -> 运算符访问成员(如 l1->val

1.2哑结点(Dummy Node)

哑结点(Dummy Node)是链表操作中常用的技巧,他是一个不存储实际数据的辅助节点,通常作为临时头节点,用于简化链表操作,尤其是在处理边界情况(如空链表、头节点变化等)时非常有用。(常用技巧,可以多加记忆!)

哑结点作用:

  1. 避免空指针异常:当链表可能为空时,使用哑结点可以确保始终有一个初始节点。
  2. 简化插入/删除操作:不需要单独处理头节点的特殊情况,所有操作都可以统一处理。
  3. 方便返回结果:最终返回 dummy.next 即可得到合并后的链表头,无需额外判断。
ListNode dummy(0);  // 创建一个哑结点,值为 0(值不重要)
ListNode* p = &dummy;  // p 是遍历指针,初始指向哑结点
  • dummy 是一个临时头节点,p 用于逐个连接 l1 和 l2 的节点。

  • 最终返回 dummy.next,因为 dummy.next 才是合并后的链表的真正头节点。

解答过程

毫无疑问,我自己没做出来,对链表知识点不熟悉了,紧急复习知识点,并学习了哑结点的使用。

我自己做是,想到了之前两个数组的排序采用的双指针,但是链表是不一样的。

采用循环+双指针的方法进行。方法二就是递归,这个也需要我好好理解一下。

1.循环+双指针解法

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {if(l1==nullptr) return l2;if(l2==nullptr) return l1;ListNode dummy(0);//哑结点用来简化操作ListNode* p=&dummy;//当前节点指针while(l1!=nullptr && l2!=nullptr){if(l1->val>=l2->val){//l1大于l2时,结果指向l2的值p->next=l2;//要移动的应该是指针,而不是直接赋值:eg:p=l2.val是错的。应该创建新节点并连接l2=l2->next;}else{//l1小于l2,结果指向l1的值p->next=l1;l1=l1->next;}p=p->next;}// if(l1!=nullptr){//     p->next=l1;// }// if(l2!=nullptr){//     p->next=l2;// }p->next=(l1!=nullptr)?l1:l2;//替换上面6行代码return dummy.next;}
};

2.递归解法

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {if(l1==nullptr) return l2;if(l2==nullptr) return l1;if(l1->val<l2->val){l1->next=mergeTwoLists(l1->next,l2);return l1;}l2->next=mergeTwoLists(l1,l2->next);return l2;}
};

相关文章:

  • 如何用vivado导出pin delay
  • DevExpressWinForms-TreeList-设置不可编辑
  • AlDente Pro for Mac电脑 充电限制保护工具 安装教程【简单,轻松上手】
  • Android学习总结之Bitmap篇
  • 单片机-89C51部分:8、定时器
  • Leetcode 3534. Path Existence Queries in a Graph II
  • 每日一道leetcode(不会做学习版,多学一题)
  • 【Redis】缓存|缓存的更新策略|内存淘汰策略|缓存预热、缓存穿透、缓存雪崩和缓存击穿
  • chatshare.xyz激活码使用说明和渠道指南!
  • JavaScript 中深拷贝浅拷贝的区别?如何实现一个深拷贝?
  • mybatis传递多个不同类型的参数到mapper xml文件
  • 本地大模型编程实战(28)查询图数据库NEO4J(1)
  • 苍穹外卖心得体会
  • 笔试专题(十二)
  • 【动态导通电阻】 GaN PiN二极管电导调制对动态 RON 的影响
  • PDF编辑器:Foxit PDF Editor Pro 版功能解析
  • Ubuntu如何查看硬盘的使用情况,以及挂载情况。
  • 浏览器自动化工具:Selenium 和 Playwright
  • 什么是全景相机?
  • 机器人--相机
  • 年轻人的事业!6家上海人工智能企业畅想“模范生”新征程
  • 新开发银行如何开启第二个“金色十年”?
  • 赛力斯拟赴港上市:去年扭亏为盈净利59亿元,三年内实现百万销量目标
  • 秦洪看盘|浮现新预期,存量资金积极调仓
  • 国家发改委答澎湃:将指导限购城市针对长期摇号家庭和无车家庭等重点群体定向增发购车指标
  • 经济日报:多平台告别“仅退款”,规则调整有何影响