Leetcode 题解 - 链表-(7)-链表求和

[LeetCode] Add Two Numbers II 两个数字相加之二

 

You are given two linked lists representing two non-negative numbers. The most significant digit comes first and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Follow up:
What if you cannot modify the input lists? In other words, reversing the lists is not allowed.

Example:

Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)

Output: 7 -> 8 -> 0 -> 7

翻转链表的话想到能有栈和递归两种

这道题是之前那道Add Two Numbers的拓展,我们可以看到这道题的最高位在链表首位置,如果我们给链表翻转一下的话就跟之前的题目一样了,这里我们来看一些不修改链表顺序的方法。由于加法需要从最低位开始运算,而最低位在链表末尾,链表只能从前往后遍历,没法取到前面的元素,那怎么办呢?我们可以利用栈来保存所有的元素,然后利用栈的后进先出的特点就可以从后往前取数字了,我们首先遍历两个链表,将所有数字分别压入两个栈s1和s2中,我们建立一个值为0的res节点,然后开始循环,如果栈不为空,则将栈顶数字加入sum中,然后将res节点值赋为sum%10,然后新建一个进位节点head,赋值为sum/10,如果没有进位,那么就是0,然后我们head后面连上res,将res指向head,这样循环退出后,我们只要看res的值是否为0,为0返回res->next,不为0则返回res即可,参见代码如下:

/**
 * 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) {
        //栈来反转链表
        Stack<Integer> s1= new Stack<>();
        Stack<Integer> s2 = new Stack<>();
        
        while(l1 != null){
            s1.push(l1.val);
            l1 = l1.next;
        }
        while(l2 != null){
            s2.push(l2.val);
            l2 = l2.next;
        }
        
        int sum = 0;
        ListNode p1 = new ListNode(0);
        while(!(s1.isEmpty() && s2.isEmpty())){
            if(!s1.isEmpty()){
                sum += s1.pop();
                
            }
            if(!s2.isEmpty()){
                sum += s2.pop();

            }
            
            p1.val = sum % 10;
            ListNode p2 = new ListNode(sum / 10);
            p2.next = p1;
            p1 = p2;
            sum /=10;
        }
        return sum == 0 ? p1.next : p1; //注意返回值考虑进不进位                                
    }
}

 

下面这种方法使用递归来实现的,我们知道递归其实也是用栈来保存每一个状态,那么也就可以实现从后往前取数字,我们首先统计出两个链表长度,然后根据长度来调用递归函数,需要传一个参数差值,递归函数参数中的l1链表长度长于l2,在递归函数中,我们建立一个节点res,如果差值不为0,节点值为l1的值,如果为0,那么就是l1和l2的和,然后在根据差值分别调用递归函数求出节点post,然后要处理进位,如果post的值大于9,那么对10取余,且res的值自增1,然后把pos连到res后面,返回res,最后回到原函数中,我们仍要处理进位情况,参见代码如下:

这里明确几点:

1. addTwoNumbers里面也需要考虑进位的情况 比如[5],[5] 这种 在help函数里面是不存在post的 无法考虑到进位 或者说[9,2][9]这中情况也是

2.help函数处理直接相加的节点 res 和 其next节点 post 根据post的值考虑进位的情况

/**
 * 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 length1= sumLength(l1), length2 = sumLength(l2);
        int diff = length1 - length2;        
        
        ListNode head = new ListNode(1);
        head.next = diff > 0 ? help(l1, l2, diff) : help(l2,l1, -diff);
        if(head.next.val > 9){
            head.next.val %= 10;
            return head;
        }
        return head.next;
    }
    private int sumLength(ListNode node){
        int sum = 0;
        while(node.next != null){
            node = node.next;
            sum++;
        }
        return sum;
    }
    private ListNode help(ListNode l1, ListNode l2, int diff){
        if(l1 == null)
            return null;
        ListNode res = diff == 0 ? new ListNode(l1.val + l2.val) : new ListNode(l1.val);
        ListNode post = diff == 0 ? help(l1.next, l2.next, 0) : help(l1.next, l2, diff - 1);
        if(post != null && post.val > 9){
            post.val %= 10;
            res.val++;
        }
        res.next = post;
        return res;
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值