zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    HDU 5671 矩阵
    HDU 5670
    UVA 11995 STL 使用
    VK Cup 2016
    字段定义
    apache用户
    apache
    使用第三方登录
    setex()
    如果客户端禁用了cookie,如何实现session
  • 原文地址:https://www.cnblogs.com/zhangyafei/p/11629875.html
Copyright © 2011-2022 走看看