mirror of
https://github.com/chefyuan/algorithm-base.git
synced 2024-11-28 14:58:55 +00:00
105 lines
4.1 KiB
Markdown
105 lines
4.1 KiB
Markdown
|
#### 面试题 02.05. 链表求和
|
|||
|
|
|||
|
之前我们一起做了链表中的几个经典题型,找到倒数第k个节点,找链表中点,判断链表中环的起点,合并链表,反转链表,删除链表中重复值。这些是链表中的经典问题,面试中也经常会考的问题,然后下面我们继续做一道链表题目,也是面试中经常会考的题目,链表求和问题。
|
|||
|
|
|||
|
另外有一些小伙伴说,虽然一天一道题不算多,但是每天读题,做题加消化稍微有点跟不上,所以我打算每个周的工作日进行更新题目,到周末的时候对本周的题目进行总结,然后为大家再写一些别的东西。下面我们一起来看一下今天的题目吧。
|
|||
|
|
|||
|
> 为保证严谨性,所有文章中的代码都在网站进行验证,大家可以放心食用。
|
|||
|
|
|||
|
题目描述:
|
|||
|
|
|||
|
给定两个用链表表示的整数,每个节点包含一个数位。
|
|||
|
|
|||
|
这些数位是反向存放的,也就是个位排在链表首部。
|
|||
|
|
|||
|
编写函数对这两个整数求和,并用链表形式返回结果。
|
|||
|
|
|||
|
示例1:
|
|||
|
|
|||
|
```java
|
|||
|
输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即617 + 295
|
|||
|
输出:2 -> 1 -> 9,即912
|
|||
|
```
|
|||
|
|
|||
|
示例2:
|
|||
|
|
|||
|
```java
|
|||
|
输入:(9 -> 9) + (9 -> 9),即99+99
|
|||
|
输出:8->9->1
|
|||
|
```
|
|||
|
|
|||
|
示例3:
|
|||
|
|
|||
|
```java
|
|||
|
输入:(5)+(5),即5+5
|
|||
|
输出:0->1
|
|||
|
```
|
|||
|
|
|||
|
**题目解析:**
|
|||
|
|
|||
|
这个题目很容易理解,就是将链表数值进行求和,刚开始做题的同学可能会有这种思路,这个题目我们分别遍历两个链表得到他们的数,然后进行相加,再放到新的链表中,但是这样是行不通的,
|
|||
|
|
|||
|
因为我们需要考虑溢出的情况,java 中 int 型的范围为 -2147483648 到 +2147483648,即 -2^31 到 2^31。
|
|||
|
|
|||
|
所以链表比较长的话进行求和就会溢出,所以我们不能提取过之后再进行相加,
|
|||
|
|
|||
|
我们应该对链表的每一位进行相加,然后通过链表的和,判断是否需要像下一位进行传递,
|
|||
|
|
|||
|
就好比小时候我们用竖式进行加法一样,判断两位相加是否大于10,大于10则进1。
|
|||
|
|
|||
|
了解了思路,但是想完全实现代码也不是特别容易,这里需要注意的三个点就是,
|
|||
|
|
|||
|
1.我们需要根据两个链表的长度,不断对新链表添加节点
|
|||
|
|
|||
|
2.需要创建一个变量用来保存进位值。
|
|||
|
|
|||
|
3.当跳出循环之后,需要根据进位值来判断需不需要再对链表长度加1.
|
|||
|
|
|||
|
这三条可以结合代码理解进行。
|
|||
|
|
|||
|
注:进位值只能是0或1,因为每一位最大为9,9+9=18;
|
|||
|
|
|||
|
![链表求和](https://cdn.jsdelivr.net/gh/tan45du/photobed@master/photo/链表求和.1yh4ymdee3k0.gif)
|
|||
|
|
|||
|
注:这里需要注意得时,链表遍历结束,我们应该跳出循环,但是我们的nlist仍在尾部添加了1节点,那是因为跳出循环时,summod值为1,所以我们需要在尾部再添加一个节点。
|
|||
|
|
|||
|
```java
|
|||
|
class Solution {
|
|||
|
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
|
|||
|
//返回链表
|
|||
|
ListNode nList = new ListNode(-1);
|
|||
|
ListNode tempnode = nList;
|
|||
|
//用来保存进位值,初始化为0
|
|||
|
int summod = 0;
|
|||
|
while(l1 != null || l2 != null) {
|
|||
|
//如果l1的链表为空则l1num为0,若是不为空,则为链表的节点值
|
|||
|
//判断是否为空,为空就设为0
|
|||
|
int l1num = l1 == null ? 0 : l1.val;
|
|||
|
int l2num = l2 == null ? 0 : l2.val;
|
|||
|
//将链表的值和进位值相加,得到为返回链表的值
|
|||
|
int sum = l1num+l2num+summod;
|
|||
|
//更新进位值,例18/10=1,9/10=0
|
|||
|
summod = sum/10;
|
|||
|
//新节点保存的值,18%8=8,则添加8
|
|||
|
sum = sum%10;
|
|||
|
//添加节点
|
|||
|
tempnode.next = new ListNode(sum);
|
|||
|
//移动指针
|
|||
|
tempnode = tempnode.next;
|
|||
|
if (l1 != null) {
|
|||
|
l1 = l1.next;
|
|||
|
}
|
|||
|
if (l2 != null) {
|
|||
|
l2 = l2.next;
|
|||
|
}
|
|||
|
}
|
|||
|
//最后根据进位值判断需不需要继续添加节点
|
|||
|
if (summod == 1) {
|
|||
|
tempnode.next = new ListNode(summod);
|
|||
|
}
|
|||
|
return nList.next;
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|