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

Leetcode算法系列(链表)之两数相加的更多相关文章

  1. 【算法题目】Leetcode算法题思路:两数相加

    在LeetCode上刷了一题比较基础的算法题,一开始也能解出来,不过在解题过程中用了比较多的if判断,看起来代码比较差,经过思考和改进把原来的算法优化了. 题目: 给出两个 非空 的链表用来表示两个非 ...

  2. 【leetcode算法-中等】2. 两数相加

    [题目描述] 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表 ...

  3. LeetCode(2): 两数相加

    本内容为LeetCode第二道题目:两数相加 # -*- coding: utf-8 -*- """ Created on Sun Mar 10 10:47:12 201 ...

  4. C语言链表之两数相加

    题目描述 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表 ...

  5. 【LeetCode】Add Two Numbers(两数相加)

    这道题是LeetCode里的第2道题. 题目要求: 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将 ...

  6. LeetCode随缘刷题之两数相加

    逐步解释,有说错的地方欢迎指正. package leetcode.day_12_03; /** * 给你两个非空 的链表,表示两个非负的整数.它们每位数字都是按照逆序的方式存储的,并且每个节点只能存 ...

  7. leetcode刷题第二天<两数相加>

    题目描述 给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表 ...

  8. [LeetCode]2.Add Two Numbers 两数相加(Java)

    原题地址: add-two-numbers 题目描述: 给你两个非空的链表,表示两个非负的整数.它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字. 请你将两个数相加,并以相同形式返回 ...

  9. 【leetcode算法-简单】1.两数之和

    [题目描述] 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个 ...

  10. [leetcode]2. Add Two Numbers两数相加

    You are given two non-empty linked lists representing two non-negative integers. The digits are stor ...

随机推荐

  1. 2020 NUPCTF pwn题目

    去年的一场比赛,今年来把去年不会做的题目来看一下,只在buu找到三道题,剩下两道好像是内核题,算了,估计找到也不会做. npuctf_2020_level2 bss段上的格式化字符串漏洞的利用. 程序 ...

  2. DNS解析超时排查/etc/resolv.conf single-request-reopen参数说明

    添加 options rotate timeout:1 attempts:3 single-request-reopen 添加到/etc/resolv.conf 中 #释义: 循环查询 超时时间 重试 ...

  3. 超链接 a 标签点击时,弹出提示框,可以按照如下来写

    onclick="return confirm('确定删除该条记录?')" 加上这条记录后,就可以在访问href属性指向的链接时,有弹出提示

  4. 【九度OJ】题目1180:对称矩阵 解题报告

    [九度OJ]题目1180:对称矩阵 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1180 题目描述: 输入一个N维矩阵,判断是否对称 ...

  5. 1434 区间LCM

    1434 区间LCM 基准时间限制:1 秒 空间限制:131072 KB 一个整数序列S的LCM(最小公倍数)是指最小的正整数X使得它是序列S中所有元素的倍数,那么LCM(S)=X. 例如,LCM(2 ...

  6. SpringMVC 五大组件

    DispatcherServlet HandleMapping Controller ModeAndView ViewResolver 1.DispatcherServlet 这个控件是SpringM ...

  7. BeanUtils属性转换工具

    commons 包的 BeanUtils 进行属性拷贝性能较差:Spring 的 BeanUtils 性能相对较好. public class A { private String name; pri ...

  8. TriggerBN ++

    目录 motivation settings results motivation 用两个BN(一个用于干净样本, 一个用于对抗样本), 结果当使用\(\mathrm{BN}_{nat}\)的时候, ...

  9. Gradient-based Hyperparameter Optimization through Reversible Learning

    目录 概 主要内容 算法 finite precision arithmic 实验 Maclaurin D, Duvenaud D, Adams R P, et al. Gradient-based ...

  10. HTML5 纯CSS3实现正方体旋转3D效果

    实现效果: 实现代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...