题目及测试
package pid002;
/*两数相加
给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
*/
public class main {
public static void main(String[] args) {
LinkList a=new LinkList(2);
a.addLast(4);
a.addLast(3);
a.printList();
//test(a.first);
LinkList b=new LinkList(5);
b.addLast(6);
b.addLast(4);
b.printList();
test(a.first,b.first);
LinkList c=new LinkList(1);
c.addLast(2);
c.addLast(2);
c.addLast(1);
c.printList();
//test(c.first);
LinkList d=new LinkList(1);
d.addLast(2);
d.addLast(3);
c.printList();
d.printList();
test(c.first,d.first);
}
private static void test(ListNode ito,ListNode ito2) {
Solution solution = new Solution();
ListNode rtn;
long begin = System.currentTimeMillis();
System.out.println();
//开始时打印数组
rtn=solution.addTwoNumbers(ito,ito2);//执行程序
long end = System.currentTimeMillis();
System.out.println("rtn=");
rtn.printNodeToEnd();
//System.out.println(":rtn" );
//System.out.print(rtn);
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(成功,41ms,很快)
因为链表的数字可能很大,使用biginteger,保存两个链表的数和它们的和
注意数字的颠倒顺序和链表的数字的顺序
package pid002;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
BigInteger num1=BigInteger.valueOf(0);
BigInteger num2=BigInteger.valueOf(0);
ListNode now=l1;
BigInteger pow10=BigInteger.valueOf(1);
while(now!=null){
int num=now.val;
num1=num1.add(pow10.multiply(BigInteger.valueOf(num)));
pow10=pow10.multiply(BigInteger.valueOf(10));
now=now.next;
}
now=l2;
pow10=BigInteger.valueOf(1);
while(now!=null){
int num=now.val;
num2=num2.add(pow10.multiply(BigInteger.valueOf(num)));
pow10=pow10.multiply(BigInteger.valueOf(10));
now=now.next;
}
BigInteger sum=num1.add(num2);
if(sum.equals(BigInteger.valueOf(0))){
return new ListNode(0);
}
ListNode result=null;
int modNow=sum.remainder(BigInteger.valueOf(10)).intValue();
sum=sum.divide(BigInteger.valueOf(10));
result=new ListNode(modNow);
now=result;
ListNode next=null;
while(!sum.equals(BigInteger.valueOf(0))){
modNow=sum.remainder(BigInteger.valueOf(10)).intValue();
next=new ListNode(modNow);
now.next=next;
now=next;
sum=sum.divide(BigInteger.valueOf(10));
}
return result;
}
}
解法2(成功,9ms,较快)
发现两个链表数字的顺序是倒着的,与做加法的顺序一样,可以类似加法,直接沿着链表做加法
链表对应结点相加时增加前一个结点的进位,并保存下一个结点的进位;
两个链表长度不一致时,要处理较长链表剩余的高位和进位计算的值;
如果最高位计算时还产生进位,则还需要添加一个额外结点。
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
// 初始节点,返回的是first.next
ListNode first=new ListNode(0);
ListNode nowNode=first;
// 进位
int carry=0;
while(l1!=null||l2!=null){
int now=carry;
if(l1!=null){
now=now+l1.val;
l1=l1.next;
}
if(l2!=null){
now=now+l2.val;
l2=l2.next;
}
carry=now/10;
now=now%10;
nowNode.next=new ListNode(now);
nowNode=nowNode.next;
}
if(carry!=0){
nowNode.next=new ListNode(carry);
}
return first.next;
}