首先看算法题描述:
1、给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
2、请你将两个数相加,并以相同形式返回一个表示和的链表。
3、你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
看了描述之后,我们能得到的信息是,数字在链表中是逆序存放的,比如我们的数字123,在链表中是3 -> 2 -> 1,这样存放的。其实这样存的好处是显而易见的,这样我们便可以从链表头部开始依次计算。
首先就是定义链表节点,代码如下:
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
}
}
有了链表定义之后,我们就可以写对应的求和方法了,代码如下:
public ListNode add(ListNode l1, ListNode l2) {
//定义一个指针指向l1,用于遍历链表l1
ListNode p1 = l1;
//定义一个指针指向l2,用于遍历链表l2
ListNode p2 = l2;
//定义一个进位的变量(当两个数字相加大于10的时候,就需要进位)
int carry = 0;
//定义一个链表用来存储相加后的结果
ListNode resultNode = new ListNode(-1);
//定义一个指针cur指向结果链表,用于给结果链表每个节点赋值
ListNode cur = resultNode;
//不断遍历两个链表,直到两个链表都遍历完才结束。其中一个链表先遍历完后,就只需要遍历剩下的那//个链表就可以了,先遍历完的那个链表的数字用0来代表。
while (p1 != null || p2 != null) {
//链表没有遍历完就取当前遍历到的节点的值,如果已经为null,则赋值为0
int num1 = p1 != null ? p1.val : 0;
int num2 = p2 != null ? p2.val : 0;
//计算两个数字之和,由于可能有进位,因此需要把进位也带上
int sum = num1 + num2 + carry;
//计算低位数(如果两个数相加后不超过10,那么就是两数之和,如果超过了10,那么低位就是取个位上的数)
int low = sum % 10;
//求和之后需要重新计算进位
carry = sum / 10;
//把两数相加的低位数添加到结果链表中
cur.next = new ListNode(low);
cur = cur.next;
//接下来就是遍历两个链表各自下一个节点了,当然,如果p1或p2指针已经指向null了,那么就不用管了,还是null就行
p1 = p1 != null ? p1.next : p1;
p2 = p2 != null ? p2.next : p2;
}
//由于在while循环中并没有处理最后的进位,如果两个链表最后的数字相加有进位的情况,那么需要把最后的进位也添加到结果链表
if (carry > 0) {
cur.next = new ListNode(carry);
}
//最后我们只需要返回结果链表即可(由于我们创建结果练笔的时候人为在头部加了一个-1的节点,要跳过它)
return resultNode.next;
}
下面我们写个测试方法来测试我们写的方法是否正确
@Test
public void test() {
//我们定义两个数,存到数组里面,顺序也是逆序,比如我们要计算203+865的和,那么我们定义的两个数组分别如下
int[] arr1 = {3, 0, 2};
int[] arr2 = {5, 6, 8};
//下面我们把两个数组组装到链表当中
ListNode l1 = new ListNode(-1);
ListNode cur1 = l1;
for (int i = 0; i < arr1.length; i++) {
cur1.next = new ListNode(arr1[i]);
cur1 = cur1.next;
}
ListNode l2 = new ListNode(-1);
ListNode cur2 = l2;
for (int i = 0; i < arr2.length; i++) {
cur2.next = new ListNode(arr2[i]);
cur2 = cur2.next;
}
ListNode result = add(l1.next, l2.next);
StringBuilder builder = new StringBuilder();
while (result != null) {
builder.append(result.val + " ");
result = result.next;
}
System.out.println(builder.toString());
}
运行得到的结果:8 6 0 1
因为我们的结果链表也是逆序的,因此两数之和1068在链表中就是8 6 0 1,可见我们的结果是正确的,我们写的方法是最优解,简单明了。