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 已收錄到公衆號,歡迎關注 :)