题目链接: https://leetcode.com/problems/add-two-numbers/
1. 题目介绍(链表相加)
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.
【Translate】: 给定两个非空链表,表示两个非负整数。数字在链表中按照倒序存储,每个节点包含一个数字。将这两个数字相加,最后以链表的形式返回总和。
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
【Translate】: 你可以假设这两个数字不包含任何前导零(eg:0011),除了数字0本身。
测试用例:
约束:
2. 题解
2.1 只适合9节点以下的链表
拿到这个题,就想着怎么莽了。不过最后发现小丑是我自己,这一题还真不能莽着来。下方代码的思路非常简单,先把l1
和l2
两个链表中的数循环遍历还原相加,得到它所表示的数值,并用一个数组将它们记录下来。之后将两个数相加,声明头节点、当前节点和一个临时节点用来切割相加后的数字,但这样做的缺点非常明显,int数值是2的32次方 = 4294967296,一旦数字超过了这个范围就会出错。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode addTwoNumbers1(ListNode l1, ListNode l2) {
int temp = 0;
int[] nums = new int[3];
for(int i = 0; l1 != null; i++){
temp = l1.val * (int)Math.pow(10, i);
nums[0] += temp;
l1 = l1.next;
}
for(int i = 0; l2 != null; i++){
temp = l2.val * (int)Math.pow(10, i);
nums[1] += temp;
l2 = l2.next;
}
int sum = nums[0]+nums[1];
nums[2] = (sum+"").length();
int[] tempArr = new int[nums[2]+1];
ListNode head = new ListNode();
ListNode curr = new ListNode();
ListNode tempNode = new ListNode();
for(int i = nums[2]-1; i >= 0; i--){
temp = sum / (int)Math.pow(10, i);
System.out.println(temp);
sum = sum % (int)Math.pow(10, i);
tempArr[i] = temp;
}
for(int i = 0; i < nums[2]; i++){
if(i == 0 && nums[2] == 1){
head.val = tempArr[i];
curr = head;
return head;
}
if(i == 0){
head.val = tempArr[i];
curr = head;
}else{
tempNode = new ListNode(tempArr[i]);
curr.next = tempNode;
curr = curr.next;
}
}
return head;
}
2.2 O(max(m,n))
【Solution】就像你在一张纸上对两个数字求和一样,我们从最低有效数开始求和,也就是l1和l2的头。由于每个数字都在0…9的范围内,两个数字相加可能会“溢出”。例如5+7= 12。在本例中,我们将当前数字设置为2,并将carry= 1带到下一次迭代中。进位必须是0或1,因为两个数字(包括进位)的最大可能和是9+9+1= 19。
和这个题解一对比,我发现我真的是too young,too simple。在Solution中,它把所有的都合在了一起操作,完全不需要算出整体数字,一位一位相加,判断是否进位即可,有进位把进位放在下一轮遍历,最后返回链表即可。
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(0);
ListNode p = l1, q = l2, curr = dummyHead;
int carry = 0;
while (p != null || q != null) {
int x = (p != null) ? p.val : 0;
int y = (q != null) ? q.val : 0;
int sum = carry + x + y;
carry = sum / 10;
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p != null) p = p.next;
if (q != null) q = q.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
return dummyHead.next;
}
3. 可参考
[1] 遇到的int型数字越界的情况
[2] Lossy Conversion in Java
[3] 关于出现incompatible types: possible lossy conversion from long to int错误(类型转化错误)