【题目描述】
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
【思路】
这道题难度一般,主要是几个特殊情况用例容易疏忽。
主要解题思路是遍历链表,将两个链表的元素取出求和后放入新的链表中,需要设置进位标志来计算进位。
需要特别关注的是遍历结束后,如果仍存在进位,此时应将这一位添加到结果链表中。
如:
输入:[5], [5]
输出:[0], [0], [1]
如果不添加最后的进位,则输出结果为[0], [0]。
参考 Leetcode官方题解。
【代码】
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
// 返回结果
ListNode *resultList = new ListNode(0);
// 新建链表保存数据,方式数据丢失
ListNode *p = l1, *q = l2, *cur = resultList;
// 进位存储
int carry = 0;
// 遍历链表求和
while(p != NULL || q != NULL){
int x = (p != NULL) ? p->val : 0;
int y = (q != NULL) ? q->val : 0;
// 计算结果
int sum = x + y + carry;
// 计算下一次进位
carry = sum / 10;
// 头节点的链表
cur->next = new ListNode (sum % 10);
// 指针指向下次计算位置
cur = cur->next;
// 循环结束标志
if(p != NULL) p = p->next;
if(q != NULL) q = q->next;
}
// 如果此时进位不为零,表示下个节点仍有数据
if(carry != 0){
cur->next = new ListNode (carry);
}
return resultList->next;
}
};
【复杂度分析】
时间复杂度:O(max(p, q))
空间复杂度:O(max(p, q))
p q链表较长的一个
【总结】
这道题主要涉及到结构体链表的一些常用操作和知识,好久没写有些遗忘。
因此将一些基本操作放出来熟悉一下。
结构体
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
题目定义的链表即为结构体。
三部分构成:
- 数据 val;
- 下一节点 next;
- 链表节点构造函数 ListNode;
因此我们可以使用ListNode * resultList = new ListNode(0);
创建一个新的链表用于存放结果。
还有一点需要特别注意的是当使用的是指针时,访问结构体成员应使用p -> val
而使用结构体定义的变量再访问时则是p.val
。在编译过程中,关键字NULL
出错,CPP中的null
不行,必须使用NULL
。
STL 中 list操作
- 定义与初始化
# include <list>
list L1 // 声明一个空的list
list L2(4, 100); // 创建包含有100 4的list
list L3(L2.begin(), L2.end()); // 使用 L2 初始化 L3
list L4(L3); // 创建L3的一个副本
list L5(size); // 创建包含有 size 个值的List
- 常用的操作方法
L.begin() // 首
L.end(); // 尾
L.clear(); // 清空
bool isEmpty = L.empty(); // 判空
L.size(); // 大小
L.sort(); // 排序
L.remove(2); // 删除相同的元素
L.reverse(); // 反转
L.push_back(10); // 尾部插入
L.push_front(10); // 头部插入
L.pop_back(); // 删除末尾值
L.insert(L1.begin(), 3, 2); // 在指定位置插入3 个 为 2 的元素
L.erase(L.begin(), L.end()); // 删除元素
// 拼接
L1.splice(position, L2); // 将L2中所有元素插入到L1的position处,L2被清空,position指向L1的那个元素
L1.splice(position, L2, iterator it); // 将L2 it的值剪切到L1中
L1.splice(position, L2 iterator first, iterator last);
// 把first 到 last 剪切到L1中
// 合并
L1.merge(L2) // 合并,在merge前,L1,L2必须有序,合并后依然有序
L.assign(L1.begin(), L1.end()); // 分配值
L.front(); // 返回第一个引用
L.back(); // 返回最后一个引用
L.rbegin(); // 返回第一个元素的前向指针
L.unique(); // 删除相邻重复元素
以上操作参考互联网