leetCode Q2:Add Two Numbers(java)

来源:互联网 发布:云计算 英文翻译 编辑:程序博客网 时间:2024/05/21 17:50

1、题目链接:https://leetcode.com/problems/add-two-numbers/description/

2、题目内容(楼主直接用中文描述了):

给两个非空链表代表两个非负整数,非负整数逆序地存储在对应的链表中(比如13存储成3->1),链表的每个节点包含一个一位的整数。

要求:将两个整数相加,结果存储在一个同样格式的链表中并返回。

例如:

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)Output: 7 -> 0 -> 8
3、思路:

这道题的难点就是进位。楼主刚开始看到这道题的时候,条件反射地以为给的两个链表的长度相同(也就是两个整数位数相同),导致后面submit的时候测试用例的好多情况都没有考虑到,吃了很多亏。楼主直接说一下本题需要注意的点:

1)两个链表都只有一位的情况:相加是否进位得判断。

2)两个链表至少有一个大于一位的情况:

a、l1链表长度大于l2或者l2链表长度大于l1;

b、最后一位是否进位得判断。

4、楼主Accepted的代码(楼主先假设l1>l2的长度,然后出来如果l2还有值,说明l2>l1,不过写得太长了,这是不熟头指针的表现):

/** * 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) {        int first = l1.val + l2.val;        ListNode answer = new ListNode(first % 10);        l1 = l1.next;        l2 = l2.next;        int flag = 0;        int temporalVal = 0;        ListNode ln1 = null;                //处理只有l1和l2都只有1个值的边界并且有进位的情况        if(l1 == null && l2 == null && (first/10) == 1) {            ln1 = new ListNode(first / 10);            answer.next = ln1;        }                //l1>=l2        while(l1 != null) {             if(flag == 0) {                ln1 = new ListNode(first / 10);                answer.next = ln1;            } else {                ListNode ln2 = new ListNode(temporalVal / 10);                ln1.next = ln2;                ln1 = ln2;            }            if(l2 != null) {    //防止当l2的长度小于l1的情况时出现null指针情况                temporalVal = l1.val + l2.val + ln1.val;                ln1.val = temporalVal % 10;                l1 = l1.next;                l2 = l2.next;            } else {                temporalVal = l1.val + ln1.val;                ln1.val = temporalVal % 10;                l1 = l1.next;            }            flag = 1;        }                //l2>=l1        while(l2 != null) {             if(flag == 0) {                ln1 = new ListNode(first / 10);                answer.next = ln1;            } else {                ListNode ln2 = new ListNode(temporalVal / 10);                ln1.next = ln2;                ln1 = ln2;            }            temporalVal = l2.val + ln1.val;            ln1.val = temporalVal % 10;            l2 = l2.next;            flag = 1;        }                //处理最后一次有进位的情况        if((temporalVal/10) == 1) {             ListNode ln2 = new ListNode(temporalVal / 10);            ln1.next = ln2;        }        return answer;    }}
(时间复杂度:O(n),空间复杂度:O(n))

运行结果:


(运行时间52ms,打败了68.80%的人)

5、leetCode简短清晰的算法:

(该代码无冗余,不像楼主将两个链表第一个数专门拿出来加完得到的结果new出answer链表的第一个结点,用头指针很好地避免了这个问题。

该算法还增加了两个整数x和y,代表当前节点的值的大小,很好地解决了对于两个链表长度不一的情况:如果链表长度不一,势必有一个链表会运行到null的时候,这个时候值会取不到,因为是null。每当其中一个链表走到null的节点,让对应的x或y值为0即可。

该代码对于进位数的判断也不冗余,都是头指针的功劳~不管是1位+1位的进位也好,还是多位+多位也好,一个判断语句就搞定。

虽然这个代码运行的时间为53ms,打败了60.52%的人,比楼主上面的运行结果差点,但是!Who care?才差那么点就少了n多工作量而且思路清晰多了!

血的教训:头指针的裨益啊!可以少了特殊情况的判断!!!!)

/** * 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) {        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;    }}
(时间复杂度:O(n),空间复杂度:O(n))

运行结果:

(运行时间:53ms,打败了60.52%的人)

原创粉丝点击