Leetcode刷题笔记之445. 两数相加Ⅱ

原题

给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。

你可以假设除了数字 0 之外,这两个数字都不会以零开头。

进阶:

如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。

示例:

输入:(7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 8 -> 0 -> 7

思路及解法

思路

这个题跟2. 两数相加基本一样。

一个是正着算,另一个是倒着算。

那么我们只要把这两个链表翻转就好了!

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
  ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) {
    l1 = reverse(l1);
    l2 = reverse(l2);
    int carry = 0;
    ListNode *ans = nullptr;
    while (l1 != nullptr || l2 != nullptr || carry != 0) {
      int a = (l1 != nullptr) ? l1->val : 0;
      int b = (l2 != nullptr) ? l2->val : 0;
      int sum = a + b + carry;
      carry = sum / 10;
      sum %= 10;
      auto cur = new ListNode(sum);
      cur->next = ans;
      ans = cur;
      if (l1 != nullptr) {
        l1 = l1->next;
      }
      if (l2 != nullptr) {
        l2 = l2->next;
      }
    }
    return ans;
  }

  ListNode *reverse(ListNode *head) {
    ListNode *node = nullptr;
    while (head) {
      ListNode *cur = head->next; //保存head->next结点信息
      head->next = node;          //反转指向
      node = head;                //后移node
      head = cur;                 //后移head
    }
    return node;
  }
};

个人觉得最难的是这几行代码,初次写代码也是不易想到的。

      auto cur = new ListNode(sum);
      cur->next = ans;
      ans = cur;

注意:这里的 new ListNode(sum) 不是指开辟一个大小为 sum 的链表!


new ListNode(sum) 不仅仅为对象 ListNode在堆上分配了空间, 而且还调用了 ListNode 的默认拷贝构造函数,生成了这个对象。

new List Node[sum] 仅仅分配了空间。


题目要求不翻转链表,那么我们用栈来实现即可!

优化

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
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() || !s2.empty() || carry != 0) {
      int a = (!s1.empty()) ? s1.top() : 0;
      int b = (!s2.empty()) ? s2.top() : 0;
      int sum = a + b + carry;
      carry = sum / 10;
      sum %= 10;
      auto cur = new ListNode(sum);
      cur->next = ans;
      ans = cur;
      if (!s1.empty()) {
        s1.pop();
      }
      if (!s2.empty()) {
        s2.pop();
      }
    }
    return ans;
  }
};

总结

许多的链表题目都可以用递归来实现。

何时使用递归(笔者的一点点看法)

  1. 能把问题拆解的;
  2. 不用递归,用循环不好解决的;
  3. 递归基数不算太大的(递归次数太多可能挤爆栈);
  4. 明显的 dfs 搜索。

诗情画意

陋室铭
刘禹锡
山不在高,有仙则名。
水不在深,有龙则灵。
斯是陋室,唯吾德馨。
苔痕上阶绿,草色入帘青。
谈笑有鸿儒,往来无白丁。
可以调素琴,阅金经。
无丝竹之乱耳,无案牍之劳形。
南阳诸葛庐,西蜀子云亭。
孔子云:何陋之有?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值