之前的blog链接:https://blog.csdn.net/weixin_43303286/article/details/131700482?spm=1001.2014.3001.5501
我用的方法是在leetcode再过一遍例题,明显会的就复制粘贴,之前没写出来就重写,然后从拓展题目中找题目来写。辅以Labuladong的文章看。然后刷题不用CLion了,使用leetcode自带模拟面试环境。
链表章节的题目都体现出思想简单,但很难一次写对的特点,注意循环后条件什么时候是空指针,防止越界访问。
这道题的整体思路就是使用两个指针,分别遍历l1和l2,取最小的那个作为结果链表p的next:
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* p1 = list1;
ListNode* p2 = list2;
ListNode* dummy = new ListNode(0), *p = dummy;
while(p1 != nullptr && p2 != nullptr){
if(p1->val > p2->val){//插入p2到res中
p->next = p2;
p2 = p2->next;
}else{
p->next = p1;
p1 = p1->next;
}
p = p->next;
}
if (p1 != NULL) {
p->next = p1;
}
if (p2 != NULL) {
p->next = p2;
}
return dummy->next;
}
};
注意循环条件,一旦跳出循环,肯定说明p1或p2有一个结束了,那么就怕剩下的那个直接接上去,使用虚拟头节点简化运算。
(什么时候需要用虚拟头结点?我这里总结下:当你需要创造一条新链表的时候,可以使用虚拟头结点简化边界情况的处理。)
2 两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,
并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
这个的意思就是说将一个数字逐位存在了链表中,其中前面存的是低位,后面存的是高位。这样对于遍历顺序来说是符合我们的加法习惯的,如果相反还难搞些。
最终代码:
// 注意:cpp 代码由 chatGPT🤖 根据我的 java 代码翻译,旨在帮助不同背景的读者理解算法逻辑。
// 本代码已经通过力扣的测试用例,应该可直接成功提交。
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
// 在两条链表上的指针
ListNode *p1 = l1, *p2 = l2;
// 虚拟头结点(构建新链表时的常用技巧)
ListNode *dummy = new ListNode(-1);
// 指针 p 负责构建新链表
ListNode *p = dummy;
// 记录进位
int carry = 0;
// 开始执行加法,两条链表走完且没有进位时才能结束循环
while (p1 != nullptr || p2 != nullptr || carry > 0) {
// 先加上上次的进位
int val = carry;
if (p1 != nullptr) {
val += p1->val;
p1 = p1->next;
}
if (p2 != nullptr) {
val += p2->val;
p2 = p2->next;
}
// 处理进位情况
carry = val / 10;
val = val % 10;
// 构建新节点
p->next = new ListNode(val);
p = p->next;
}
// 返回结果链表的头结点(去除虚拟头结点)
return dummy->next;
}
};