数据结构与算法之深入解析“两数相加II”的求解思路与算法示例

Posted Serendipity·y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法之深入解析“两数相加II”的求解思路与算法示例相关的知识,希望对你有一定的参考价值。

一、题目要求

  • 给你两个非空链表来代表两个非负整数,数字最高位位于链表开始位置,它们的每个节点只存储一位数字,将这两数相加会返回一个新的链表。
  • 可以假设除了数字 0 之外,这两个数字都不会以零开头。
  • 示例1:

输入:l1 = [7,2,4,3], l2 = [5,6,4]
输出:[7,8,0,7]
  • 示例2:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[8,0,7]
  • 示例3:
输入:l1 = [0], l2 = [0]
输出:[0]
  • 提示:
    • 链表的长度范围为 [1, 100];
    • 0 <= node.val <= 9;
    • 输入数据保证链表代表的数字无前导 0。

二、求解算法

① 栈

  • 本题的主要难点在于链表中数位的顺序与我们做加法的顺序是相反的,为了逆序处理所有数位,可以使用栈:把所有数字压入栈中,再依次取出相加,计算过程中需要注意进位的情况。
  • C++ 示例:
class Solution 
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) 
        stack<int> s1, s2;
        while (l1) 
            s1.push(l1 -> val);
            l1 = l1 -> next;
        
        while (l2) 
            s2.push(l2 -> val);
            l2 = l2 -> next;
        
        int carry = 0;
        ListNode* ans = nullptr;
        while (!s1.empty() or !s2.empty() or carry != 0) 
            int a = s1.empty() ? 0 : s1.top();
            int b = s2.empty() ? 0 : s2.top();
            if (!s1.empty()) s1.pop();
            if (!s2.empty()) s2.pop();
            int cur = a + b + carry;
            carry = cur / 10;
            cur %= 10;
            auto curnode = new ListNode(cur);
            curnode -> next = ans;
            ans = curnode;
        
        return ans;
    
;
  • Java 示例:
class Solution 
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) 
        Deque<Integer> stack1 = new LinkedList<Integer>();
        Deque<Integer> stack2 = new LinkedList<Integer>();
        while (l1 != null) 
            stack1.push(l1.val);
            l1 = l1.next;
        
        while (l2 != null) 
            stack2.push(l2.val);
            l2 = l2.next;
        
        int carry = 0;
        ListNode ans = null;
        while (!stack1.isEmpty() || !stack2.isEmpty() || carry != 0) 
            int a = stack1.isEmpty() ? 0 : stack1.pop();
            int b = stack2.isEmpty() ? 0 : stack2.pop();
            int cur = a + b + carry;
            carry = cur / 10;
            cur %= 10;
            ListNode curnode = new ListNode(cur);
            curnode.next = ans;
            ans = curnode;
        
        return ans;
    

② 反转链表

  • 先把两个链表反转后再相加,因为从低位开始做加法比较直观,加法运算完成后再反转整个链表后返回。
  • 反转之后的链表的头节点表示个位数,尾节点表示最高位;从两个链表的头节点开始相加,就相当于从整数的个位数开始相加。
  • 要注意进位,如果两个整数的个位数相加的和超过 10,就会往十位数产生一个进位,在下一步做十位数相加时就要把这个进位考虑进去。
  • C++ 示例:
class Solution 
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) 
        // 若任一链表为空,则直接返回另一链表
        if (l1 == nullptr || l2 == nullptr) return l1 == nullptr ? l2 : l1;
        l1 = reverseList(l1), l2 = reverseList(l2);     // 反转链表,便于进行加法运算
        return reverseList(addList(l1, l2));            // 相加后再反转,最后返回结果
    

	// 反转链表模板
    ListNode* reverseList(ListNode* head) 
        if (head == nullptr) return head;

        ListNode *pre = head, *cur = head->next;
        while (cur) 
            ListNode *ne = cur->next;
            cur->next = pre;
            pre = cur, cur = ne;
        
        head->next = nullptr;
        return pre;
    

	// 链表相加
    ListNode* addList(ListNode* l1, ListNode* l2) 
        ListNode *dummy = new ListNode(0);
        ListNode *p = dummy;

        int carry = 0;     // 进位标志
        while (l1 || l2) 
            // 节点不为空就将当前的两个节点的值加起来,为空就加0
            carry += (l1 == nullptr ? 0 : l1->val) + (l2 == nullptr ? 0 : l2->val);
            
            // 如果当前节点有进位,就对10取模,没有进位就保持原值
            // p = p->next = xx 表示 p->next = xx, p = p->next两条语句的组合
            p = p->next = new ListNode(carry % 10);
            
            // 如果有进位,则carry余1, 没有进位则carry重置为0
            carry /= 10;

            if (l1) l1 = l1->next;
            if (l2) l2 = l2->next;
        

        // 判断最高位是否有进位,有的话就再追加一个1即可
        if (carry) p->next = new ListNode(1);
        return dummy->next;
    
;

以上是关于数据结构与算法之深入解析“两数相加II”的求解思路与算法示例的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法之深入解析“股票的最大利润”的求解思路与算法示例

数据结构与算法之深入解析“安装栅栏”的求解思路与算法示例

数据结构与算法之深入解析“最长连续序列”的求解思路与算法示例

数据结构与算法之深入解析“路径总和”的求解思路与算法示例

数据结构与算法之深入解析“斐波那契数”的求解思路与算法示例

数据结构与算法之深入解析“连续整数求和”的求解思路与算法示例