leetCode Q2:Add Two Numbers(java)

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%的人)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值