[Leetcode题解]2. 两数相加-链表遍历和重构

1. 审题leetcode 02 add-two-numbers​

我们先看一下题目,如下  :

链表的从前往后为数字的低位到高位,模拟加法手算过程,从前往后遍历即可, 注意每个数字0-9,进位要处理好;


2. 解体思路

主要分4步来完成,增加一个头节点来处理后续的添加过程可能简单些;

  • 处理l1 和 l2 共有元素的累加, 注意进位inc的累加;
  • 处理多余的l1的内容;
  • 处理多余的l2的内容;
  • 处理最后剩余的进位;

3. 详细代码

3.1 直观的循环代码

 1 /**
 2  * Definition for singly-linked list.
 3  * type ListNode struct {
 4  *     Val int
 5  *     Next *ListNode
 6  * }
 7  */
 8  
 9 func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
10     var inc int
11     head := ListNode{0, nil}
12     lastNode := &head
13     for ; l1 != nil && l2 != nil; l1, l2 = l1.Next, l2.Next {
14         sum := l1.Val + l2.Val + inc
15         if sum >= 10 {
16             inc = 1
17             sum -= 10
18         } else {
19             inc = 0
20         }
21         temp := ListNode{sum, nil}
22         lastNode.Next = &temp
23         lastNode = &temp
24     }
25     for ; l1 != nil; l1 = l1.Next {
26         sum := l1.Val + inc
27         if sum >= 10 {
28             inc = 1
29             sum -= 10
30         } else {
31             inc = 0
32         }
33         temp := ListNode{sum, nil}
34         lastNode.Next = &temp
35         lastNode = &temp
36     }
37     for ; l2 != nil; l2 = l2.Next {
38         sum := l2.Val + inc
39         if sum >= 10 {
40             inc = 1
41             sum -= 10
42         } else {
43             inc = 0
44         }
45         temp := ListNode{sum, nil}
46         lastNode.Next = &temp
47         lastNode = &temp
48     }
49     if inc != 0 {
50         temp := ListNode{inc, nil}
51         lastNode.Next = &temp
52         lastNode = &temp
53     }
54     return head.Next
55 }

3.2 函数提炼重构

每个计算过程都包含取出两个数字,和进位一起求和,处理大于10的数字,继续下一轮;故抽取关键函数完成这个节点的处理

 1 func addSumNode(n1 int, n2 int, inc int, lastNode *ListNode) (int, *ListNode) {
 2     sum := n1 + n2 + inc
 3     if sum >= 10 {
 4         inc = 1
 5         sum -= 10
 6     } else {
 7         inc = 0
 8     }
 9     temp := ListNode{sum, nil}
10     lastNode.Next = &temp
11     lastNode = &temp
12     return inc, lastNode
13 }
14 
15 func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
16     var inc int
17     head := ListNode{0, nil}
18     lastNode := &head
19     for ; l1 != nil && l2 != nil; l1, l2 = l1.Next, l2.Next {
20         inc, lastNode = addSumNode(l1.Val, l2.Val, inc, lastNode)
21     }
22     for ; l1 != nil; l1 = l1.Next {
23         inc, lastNode = addSumNode(l1.Val, 0, inc, lastNode)
24     }
25     for ; l2 != nil; l2 = l2.Next {
26         inc, lastNode = addSumNode(0, l2.Val, inc, lastNode)
27     }
28     if inc != 0 {
29         inc, lastNode = addSumNode(0, 0, inc, lastNode)
30     }
31     return head.Next
32 }

4. 感悟总结

要重构代码不是特别难做的事情, 看到两次以上的重复就要有所警觉, 尝试提取公共部分,或者进一步优化代码整体结构, 你会发现代码是越来越容易懂,后续添加新需求也实现其来更加容易,更好复用,所以, 重构无小事, 重构也“不是难做的大事”,因为重构也就在点滴中; 小步快跑才是重构的精髓;

重构后代码看起来清爽很多, 55LOC => 32 LOC

运行时间对比:

执行用时:16 ms, 在所有 Go 提交中击败了39.76% 的用户
内存消耗:4.9 MB, 在所有 Go 提交中击败了21.00% 的用户

# 重构后
执行用时:12 ms, 在所有 Go 提交中击败了72.62% 的用户
内存消耗:4.9 MB, 在所有 Go 提交中击败了26.81% 的用户

永久地址: https://mp.weixin.qq.com/s/5OZx7i-oOGvDbxCWHPxi5A 已收录到公众号,欢迎关注 :)

原文地址:https://www.cnblogs.com/QuLory/p/13837796.html