【leecode面试题】两数相加

题目描述

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

1. 链表本身的Val的范围是0到9,两个链表Val相加结果可能会超过10,会产生进位(carry),这个进位要作为链表下一个节点(Next)的Val处理要加的数值

2. 链表l1和l2长度不一定相等,有可能一个链表结束(Next指向Null),另一个链表仍然有有效节点

3. 两个链表全部处理完毕可能会产生进位,所以两个链表全部处理完毕后,要考虑如果产生了进位,该进位需要作为结果链表的新节点

4. 两个链表全部处理完毕的条件需要是 链表l1和l2都为NULL,就退出golang的for处理代码块

 

要考虑的场景

1. 两个链表都只有一个节点,但是有进位

l1: [5]

l2: [5]

进位为1

2. 一个链表为空,一个链表非空

l1: []

l2: [5, 7, 9]

3. l1和l2非空,长度不相等

l1: [5, 3, 8]

l2: [4, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 9]

 

代码实现

package main

import (
    "fmt"
    "strconv"
)

// Definition for singly-linked list.
type ListNode struct {
    Val  int
    Next *ListNode
}

// Rule
// 1. for循环退出的条件是l1和l2都为nil,代表两条链表全部处理完毕
// 场景考虑
// 1. l1和l2全部处理完毕,但是有进位(carry=1), 需要在for循环退出后,将carry当作Val新增一个节点
// 2. l1为空,l2非空
// 3. l1和l2非空,长度相等
// 4. l1和l2非空,长度不相等
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {

    var head, curr, node *ListNode
    var carry int

    for {
        var a, b, sum, val int

        if l1 == nil && l2 == nil {
            break
        }

        if l1 != nil {
            a = l1.Val
            l1 = l1.Next
        }

        if l2 != nil {
            b = l2.Val
            l2 = l2.Next
        }

        sum = a + b + carry
        if sum >= 10 {
            carry = 1
            val = sum % 10
        } else {
            carry = 0
            val = sum
        }

        if curr == nil {
            head = &ListNode{
                Val: 0,
            }
            node = &ListNode{
                Val: val,
            }
            head.Next = node
            curr = node
        } else {
            node = &ListNode{
                Val: val,
            }
            curr.Next = node
            curr = node
        }
    }

    // l1 and l2 all processed, but has carry(carry=1)
    if carry == 1 && curr != nil {
        node = &ListNode{
            Val: carry,
        }
        curr.Next = node
    }

    if head == nil {
        return nil
    }

    return head.Next
}

// 模拟打印链表
func printListNode(l *ListNode) {
    var nums []int
    for {
        if l == nil {
            break
        }
        nums = append(nums, l.Val)
        l = l.Next
    }

    fmt.Printf("ListNode=%+v\n", nums)
}

// 模拟构建数值链表
func buildListNode(s string) *ListNode {

    var p, n *ListNode

    for _, b := range s {
        v, err := strconv.Atoi(fmt.Sprintf("%c", b))
        if err != nil {
            return nil
        }
        if n == nil {
            l := &ListNode{
                Val: v,
            }
            n = l
            p = n
        } else {
            l := &ListNode{
                Val: v,
            }
            n.Next = l
            n = l
        }
        //fmt.Printf("%c\n", b)
    }

    return p
}

// 入口函数,各种场景测试
func main() {

    // l1 长度远远大于l2,且中间有进位
    l1 := buildListNode("1001000000000000000000000000001")
    l2 := buildListNode("5649")
    l := addTwoNumbers(l1, l2)
    printListNode(l)
    // 输出结果:
    // ListNode=[6 6 4 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]

    // l1和l2长度相等,且节点运算完后有进位
    l1 = buildListNode("5")
    l2 = buildListNode("5")
    l = addTwoNumbers(l1, l2)
    printListNode(l)
    // 输出结果:
    // ListNode=[0 1]

    // l1为空, l2非空
    l1 = buildListNode("")
    l2 = buildListNode("5649")
    l = addTwoNumbers(l1, l2)
    printListNode(l)
    // 输出结果:
    // ListNode=[5 6 4 9]
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值