Leetcode算法系列(链表)之两数相加
难度:中等
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
链接:https://leetcode-cn.com/problems/add-two-numbers
Python实现
# Definition for singly-linked list. class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: @staticmethod def addTwoNumbers(l1, l2): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode 方法一:按字符串-数字处理 1. 链表节点转化为拼接字符串 2. 字符串反转并转化为数字 3. 两个数字相加求和 4. 创建链表,将结果逆序插入 通过 92 ms 13.8 MB Python """ str1 = str2 = '' while l1: str1 += str(l1.val) l1 = l1.next while l2: str2 += str(l2.val) l2 = l2.next str1 = str1[::-1] str2 = str2[::-1] sum_two = str(int(str1) + int(str2)) list_ret = [ListNode(int(num)) for num in sum_two] i = 0 list_len = len(list_ret) while i < (list_len - 1): list_ret[list_len - i - 1].next = list_ret[list_len - i -2] i += 1 return list_ret[list_len-1] def addTwoNumbers2(self, l1, l2): """ 方法二:按位相加 初始化返回列表l,复制列表l_copy 将进位 carry 初始化为 0。 遍历列表 l1 和 l2 直至到达它们的尾端 获取l1,l2链表节点中的val,若一方到达末尾另一方为到达则补0 设定 sum = l1_val + l2_val + carry。 更新进位的值,若sum >= 10, carry = 1,否则 carry = 0 创建一个数值为 (sum % 10) 的新结点,并将其设置为当前结点的下一个结点,然后将当前结点前进到下一个结点。 同时,将 l1 和 l2 前进到下一个结点。 检查最高位carry = 1是否成立,如果成立,则向返回列表l_copy追加一个含有数字1的新结点。 返回列表l的的第一个结点。 通过 72 ms 13.9 MB Python3 """ l = ListNode(0) l_copy = l # 定义两数相加是否大于10进位 carry = 0 while l1 or l2: # 因为l1与l2链表对应的位数可能不同,此时需要将空缺的位置补0 l1_val = l1.val if l1 else 0 l2_val = l2.val if l2 else 0 two_sum = l1_val + l2_val + carry if two_sum < 10: l_copy.next = ListNode(two_sum) carry = 0 else: carry = two_sum//10 l_copy.next = ListNode(two_sum%10) l_copy = l_copy.next l1 = l1.next if l1 else None l2 = l2.next if l2 else None if carry > 0: l_copy.next = ListNode(carry) return l.next def addTwoNumbers3(self, l1, l2): """ 方法三:递归求解 1. 初始化进位carry=0 2. 判断:若l1,l2都到达末尾,如果carry=1,则返回节点1,否则为None 3. 获取l1,l2当前节点值,若连表到达末尾则补0 4. 定义相加规则:val = l1.val + l2.val + carry 5. l1.val=val%10, l1.next=addNone(l1.next, l2.next, carry=val>9),递归求解 """ return self.addNode(l1, l2, carry=0) def addNode(self, l1, l2, carry): if not (l1 or l2): return ListNode(1) if carry else None l1, l2 = l1 or ListNode(0), l2 or ListNode(0) val = l1.val + l2.val + carry l1.val, l1.next = val % 10, self.addNode(l1.next, l2.next, val > 9) return l1 def data_preparation(list1, list2): print(list1, list2) list1_nodes = [ListNode(x=node) for node in list1] list2_nodes = [ListNode(x=node) for node in list2] i = 0 while i < len(list1_nodes) - 1: list1_nodes[i].next = list1_nodes[i + 1] i += 1 i = 0 while i < len(list2_nodes) - 1: list2_nodes[i].next = list2_nodes[i + 1] i += 1 return list1_nodes[0], list2_nodes[0] def print_lnode(lnode): while lnode: print(lnode.val) lnode = lnode.next if __name__ == "__main__": node1, node2 = data_preparation(list1=[2,4,3], list2=[5,6,4]) solution = Solution() L3 = solution.addTwoNumbers(l1=node1, l2=node2) L4 = solution.addTwoNumbers2(l1=node1, l2=node2) L5 = solution.addTwoNumbers3(l1=node1, l2=node2) print_lnode(L3) print_lnode(L4) print_lnode(L5)
Go语言实现
package main import "fmt" // Definition for singly-linked list. type ListNode struct { Val int Next *ListNode } func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode { // 按位相加 var l *ListNode = &ListNode{} pre := l flag := 0 for l1 != nil || l2 != nil { pre.Next = &ListNode{} p := pre.Next x := 0 y := 0 if l1 != nil { x = l1.Val } if l2 != nil { y = l2.Val } p.Val = (x + y + flag) % 10 flag = (x + y + flag) / 10 pre = p if l1 != nil { l1 = l1.Next } if l2 != nil { l2 = l2.Next } } if flag != 0 { pre.Next = &ListNode{Val: flag} } return l.Next } func (h *ListNode) Append(i int) { for h.Next != nil { h = h.Next } h.Next = &ListNode{Val: i} } func (h *ListNode) Show() { fmt.Println(h.Val) for h.Next != nil { h = h.Next fmt.Println(h.Val) } } func addTwoNumbers2(l1 *ListNode, l2 *ListNode) *ListNode { // 递归求解 return addNode(l1, l2, 0) } func addNode(l1 *ListNode, l2 *ListNode, pre int) *ListNode { if l1 == nil && l2 == nil { if pre != 0 { return &ListNode{Val: pre} } else { return nil } } if l1 == nil { l1 = &ListNode{Val: 0} } if l2 == nil { l2 = &ListNode{Val: 0} } totalSum := l1.Val + l2.Val + pre i, j := totalSum/10, totalSum%10 l := new(ListNode) l.Val = j l.Next = addNode(l1.Next, l2.Next, i) return l } func create_link_list(list1 []int) *ListNode { head := &ListNode{Val: list1[0]} tail := head for i := 1; i < len(list1); i++ { tail.Next = &ListNode{Val: list1[i]} tail = tail.Next // head.Append(list1) } return head } func main() { list1 := []int{2, 4, 3} list2 := []int{5, 6, 4} fmt.Println(list1, list2) head1 := create_link_list(list1) head2 := create_link_list(list2) head3 := addTwoNumbers(head1, head2) head4 := addTwoNumbers2(head1, head2) head3.Show() head4.Show() }
- 执行结果
方法 | 执行用时 | 内存消耗 | 语言 |
---|---|---|---|
python字符串-数字转化 | 92 ms | 13.8 MB | Python3 |
python按位相加 | 72 ms | 13.9 MB | Python3 |
python递归 | 80 ms | 14 MB | Python3 |
go 按位相加 | 8 ms | 5 MB | Golang |
go 递归求解 | 20 ms | 5 MB | Golang |