首先看算法题描述:
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,用于遍历链表l1ListNode p1 = l1;//定义一个指针指向l2,用于遍历链表l2ListNode p2 = l2;//定义一个进位的变量(当两个数字相加大于10的时候,就需要进位)int carry = 0;//定义一个链表用来存储相加后的结果ListNode resultNode = new ListNode(-1);//定义一个指针cur指向结果链表,用于给结果链表每个节点赋值ListNode cur = resultNode;//不断遍历两个链表,直到两个链表都遍历完才结束。其中一个链表先遍历完后,就只需要遍历剩下的那//个链表就可以了,先遍历完的那个链表的数字用0来代表。while (p1 != null || p2 != null) {//链表没有遍历完就取当前遍历到的节点的值,如果已经为null,则赋值为0int 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,可见我们的结果是正确的,我们写的方法是最优解,简单明了。