【leet-code清晰解题思路✅】2. 两数相加

126 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

题目描述

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

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

示例 1:

输入: l1 = [2,4,3], l2 = [5,6,4]
输出: [7,0,8]
解释: 342 + 465 = 807.

示例 2:

输入: l1 = [0], l2 = [0]
输出: [0]

示例 3:

输入: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出: [8,9,9,9,0,0,0,1]

提示:

  • 每个链表中的节点数在范围 [1, 100] 内
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

解题思路

  • 加法我们小学都学过,就是从右向左按位相加,并处理进位。根据数据范围,直接转化成整数相加会越界,因此要保持链表的存储格式,按位计算。题目给的链表是逆序的,所以我们只要从左向右按位相加并进位即可。O(n+m)
  • 边界条件
    • 链表节点数为0
    • 两链表等长,最后有进位
    • 两链表不等长,最后有进位
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
   head := &ListNode{}
   t := head
   pre := 0
   for l1 != nil && l2 != nil {
      t.Next = &ListNode{(pre + l1.Val + l2.Val) % 10, nil}
      pre = (pre + l1.Val + l2.Val) / 10
      l1 = l1.Next
      l2 = l2.Next
      t = t.Next
   }
   if l1 != nil || l2 != nil {
      var p *ListNode
      if l1 != nil {
         p = l1
      } else {
         p = l2
      }
      for p != nil {
         t.Next = &ListNode{(pre + p.Val) % 10, nil}
         pre = (pre + p.Val) / 10
         p = p.Next
         t = t.Next
      }
   }

   if pre != 0 {
      t.Next = &ListNode{1, nil}
   }
   return head.Next
}

image.png

  • 常数级优化:在处理剩余的单个链表时,如果没有进位可以直接把剩下的链表拼接到结果里直接结束。

func addTwoNumber(l1 *ListNode, l2 *ListNode) *ListNode {
   head := &ListNode{}
   t := head
   pre := 0
   for l1 != nil && l2 != nil {
      t.Next = &ListNode{(pre + l1.Val + l2.Val) % 10, nil}
      pre = (pre + l1.Val + l2.Val) / 10
      l1 = l1.Next
      l2 = l2.Next
      t = t.Next

   }
   if l1 != nil || l2 != nil {
      var p *ListNode
      if l1 != nil {
         p = l1
      } else {
         p = l2
      }
      for p != nil {
         t.Next = &ListNode{(pre + p.Val) % 10, nil}
         pre = (pre + p.Val) / 10
         p = p.Next
         t = t.Next
         if pre == 0 {
            t.Next = p
            break
         }
      }
   }
   if pre != 0 {
      t.Next = &ListNode{1, nil}
   }
   return head.Next
}

image.png

  • 也可以有更优雅的写法
func addTwoNumbers3(l1 *ListNode, l2 *ListNode) *ListNode {
   head := &ListNode{}
   tail := head
   t := 0
   for l1 != nil || l2 != nil || t != 0 {
      if l1 != nil {
         t += l1.Val
         l1 = l1.Next
      }
      if l2 != nil {
         t += l2.Val
         l2 = l2.Next
      }
      tail.Next = &ListNode{t % 10, nil}
      tail = tail.Next
      t /= 10
   }
   return head.Next
}

image.png