Leetcode算法系列(链表)之两数相加

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
posted @ 2019-10-07 11:38  DreamBoy_张亚飞  阅读(300)  评论(0编辑  收藏  举报