题目(难度:中等):
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
解法:
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
public class Solution2 {
static ListNode head = new ListNode(0);
static ListNode headfirst = head;
public static void printNode(ListNode node,String str){
System.out.println("This is content of "+str+":");
while(node!=null){
System.out.print(node.val+" ");
node=node.next;
}
System.out.println();
}
public static void newNode(int var){
ListNode node = new ListNode(var);
head.next=node;
node.next = null;
head=node;
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int temp = 0, sum = 0;
boolean flag = false;
ListNode p = l1, q = l2;
head.next=null;
while (p != null && q != null) {
sum = p.val + q.val;
if (sum >= 10) {
temp = sum - 10;
if (flag == true) {
temp = temp + 1;
Solution2.newNode(temp);
flag = true;
} else {
Solution2.newNode(temp);
flag = true;
}
} else {
if (flag == true) {
sum+=1;
Solution2.newNode(sum);
flag = false;
} else {
Solution2.newNode(sum);
}
}
p = p.next;
q = q.next;
}
if (p == null) {
while (q != null) {
if (flag == true) {
Solution2.newNode(q.val+1);
flag = false;
} else {
Solution2.newNode(q.val);
}
q = q.next;
}
} else {
while (p != null) {
if (flag == true) {
Solution2.newNode(p.val+1);
flag = false;
} else {
Solution2.newNode(p.val);
}
p = p.next;
}
}
return headfirst.next;
}
public static void main(String[] args) {
Random rand = new Random(10);
ListNode head1 = null, head2 = null;
int temp = 0;
for (int i = 0; i < 2; i++) {
ListNode newnode = new ListNode(rand.nextInt(10) + 1);
newnode.next = head1;
head1 = newnode;
}
for (int i = 0; i < 3; i++) {
ListNode newnode = new ListNode(rand.nextInt(10) + 1);
newnode.next = head2;
head2 = newnode;
}
ListNode node1 = head1;
Solution2.printNode(node1,"head1");
ListNode node2 = head2;
Solution2.printNode(node2,"head2");
Solution2 solution2 = new Solution2();
ListNode node = solution2.addTwoNumbers(head1, head2);
Solution2.printNode(node,"result");
}
}
输出结果:
存在问题:创建新节点时,代码重复率高
优化:
利用一个溢出位temp,每次新建一个链表结点,其值为 temp + x + y ,最后需要判断一下当 L1 和 L2均结束后,进位temp是不是为1,有则再新建一个节点存储进位。,否则结束。
代码实现:
public ListNode addTwoNumbers(ListNode l1,ListNode l2){
ListNode p = l1,q = l2;
ListNode dummyNode = new ListNode(0);
ListNode current =dummyNode;
int temp = 0;
while(p!=null || q!=null){
int x=(p!=null)?p.val:0; //L1链表是否结束
int y = (q!=null)?q.val:0; //L2链表是否结束
int sum = x+y+temp;
temp = sum/10;
current.next = new ListNode(sum%10);
current=current.next;
if(p!=null) p=p.next;
if(q!=null) q=q.next;
}
if(temp>0){ //最后判断一下有没有进位
current.next=new ListNode(temp);
}
return dummyNode.next;
}
测试用例:
算法分析:
时间复杂度:O(max(m,n)), m为链表 l1 的长度,n为链表 l2 的长度
空间复杂度:O(max(m,n))