文章目录
- 前言
- 一、两数相加
- 1, 题目
- 2, 思路分析
- 3, 代码
前言
各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你:
📕 JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等
📗 Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等
📘 JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)
对于链表题, 常用的技巧和操作是: 头插, 尾插, 快慢双指针, 傀儡节点
一、两数相加
1, 题目
OJ链接
题目给定的链表是倒序排列的, 这一点方便了我们进行遍历两个链表
2, 思路分析
本题的基本思路就是: 模拟两数加法的过程 + 构建新链表
- 模拟两数相加: 需要考虑 “进位”, 因为题目规定每个结点只能存储一个数字, 所以形如 4 + 6 = 10, 7 + 7 = 14, 两数之和 > 9 的情况, 新结点中只能存储个位数, 那么十位上的 “1”, 就要加到后面的结点上
- 构建新链表: 可以使用傀儡头结点的技巧, 每 new 出一个新结点就尾插到新的链表后面
准备工作如下:
- 定义一个傀儡头结点 phead
- 定义一个指针 cur, 指向 phead
- 定义两个指针 cur1, cur2, 分别指向两个链表的头节点 l1, l2
- 定义一个变量 carry, 表示进位
具体流程如下:
- 1, carry = 2 + 5 = 7, carry / 10 = 0, 无需进位, 新结点的值就是 7
-
2, carry = 4 + 6 = 10, carry / 10 = 1, 需要进位 “1”, 新结点的值为 0 ,
进位 1 留给下一个结点
-
3, carry = 3 + 4 + 1 = 8 注意这里的 “1” 表示上一步的 “进位1” , carry / 10 = 0, 不需要进位, 新结点的值为 8
此时 cur1 和 cur 2 再往后走就是链表的末尾了, 但是还没完 ! ! ! 还有一个细节 ! ! !
假设: 两个链表末尾还有进位的情况, 如下图
此时 cur1 和 cur2 也即将遍历到链表末尾, 但是有进位1, 所以还需要再给新链表 再尾插一个值为 1 的结点
此时 cur1 和 cur2 都指向了 null, carry 也为 0, 这才算真正的结束
上述当 cur1 和 cur2 都遍历到 null 时, carry 是否为 1 的判断可以放到 while 循环中, 也可以最后单独做一个 if 判断
最终返回新链表的头结点, 返回 phead.next 即可
3, 代码
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if(l1 == null || l2 == null) {
return null;
}
ListNode phead = new ListNode(0); // 傀儡头结点
ListNode cur1 = l1;
ListNode cur2 = l2;
ListNode cur = phead;
int carry = 0; // 表示进位
while(cur1 != null || cur2 != null || carry != 0) {
if(cur1 != null) {
carry += cur1.val;
cur1 = cur1.next;
}
if(cur2 != null) {
carry += cur2.val;
cur2 = cur2.next;
}
cur.next = new ListNode(carry % 10);
carry /= 10; // 表示进位
cur = cur.next;
}
return phead.next;
}