2020.06.01 力扣 - 链表 - 02 两数相加

126 阅读3分钟

题目

给出两个非空的链表用来表示两个非负的整数。

其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。

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

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

示例

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)

输出:7 -> 0 -> 8

原因:342 + 465 = 807

代码示例

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
}

思路

从今天开始就要开始打卡链表啦!

与数组很长的区别就是,我在测试的时候不能直接通过声明就拿到一个链表,需要自己实现。

很久没写过链表的代码,上来也是有点懵,但是别气馁。

把这个问题进行拆解,第一步,构造链表;第二步,再解题。

哈哈哈,就是这么简单。

先是找度娘看看现成的用golang实现链表的方案,此处贴上(studygolang.com/articles/17…)。

他是从头到尾创建的,但咱们这道题,已经给了node的结构定义,所以就不适用了,自己动手丰衣足食!

边看边想,自己想要的初始化,就写出来了 => 从后往前,这不就解决了!

接着这个思想对咱们这道题也是使用的,我们先遍历计算出每一位上数字和,放进数组中,最后再对数组初始化不能OK了吗!

代码

// 节点
type ListNode struct {
	Val  int
	Next *ListNode
}

func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	if l1 == nil {
		return l2
	}

	if l2 == nil {
		return l1
	}

	var sums []int
	sum := 0
	carry := 0
	for l1 != nil && l2 != nil {
		sum, carry = add(l1.Val, l2.Val+carry)
		fmt.Println("sum: ", sum)
		sums = append(sums, sum)

		l1 = l1.Next
		l2 = l2.Next
	}

	for l1 != nil {
		sum, carry = add(l1.Val, carry)
		fmt.Println("sum: ", sum)
		sums = append(sums, sum)
		l1 = l1.Next
	}

	for l2 != nil {
		sum, carry = add(l2.Val, carry)
		fmt.Println("sum: ", sum)
		sums = append(sums, sum)
		l2 = l2.Next
	}

	if carry != 0 {
		fmt.Println("sum: ", carry)
		sums = append(sums, carry)
	}

	var ret *ListNode
	for i := len(sums) - 1; i >= 0; i-- {
		node := &ListNode{
			Val:  sums[i],
			Next: nil,
		}
		ret = Append(ret, node)
	}

	return ret
}

func add(a, b int) (ret, carry int) {
	sum := a + b
	sumArr := fmt.Sprintf("%d", sum)
	if len(sumArr) > 1 {
		ret, _ = strconv.Atoi(sumArr[1:])
		carry, _ = strconv.Atoi(sumArr[:1])
	} else {
		ret = sum
		carry = 0
	}
	return
}

func Append(list, node *ListNode) *ListNode {
	if list == nil {
		return node
	}
	node.Next = list
	return node
}

测试

func main() {
	nums1 := []int{2, 4, 3}
	var list1 *ListNode
	for i := len(nums1) - 1; i >= 0; i-- {
		node := &ListNode{
			Val:  nums1[i],
			Next: nil,
		}
		list1 = Append(list1, node)
	}
	fmt.Println(list1)

	nums2 := []int{5, 6, 4}
	var list2 *ListNode
	for i := len(nums2) - 1; i >= 0; i-- {
		node := &ListNode{
			Val:  nums2[i],
			Next: nil,
		}
		list2 = Append(list2, node)
	}
	fmt.Println(list2)
	
	// 等长两数组求和
	ret := addTwoNumbers(list1, list2)
	fmt.Println(ret)

	nums3 := []int{9, 8}
	var list3 *ListNode
	for i := len(nums3) - 1; i >= 0; i-- {
		node := &ListNode{
			Val:  nums3[i],
			Next: nil,
		}
		list3 = Append(list3, node)
	}
	fmt.Println(list3)

	nums4 := []int{1}
	var list4 *ListNode
	for i := len(nums4) - 1; i >= 0; i-- {
		node := &ListNode{
			Val:  nums4[i],
			Next: nil,
		}
		list4 = Append(list4, node)
	}
	fmt.Println(list4)
	
	// 一长一短数组求和
	ret = addTwoNumbers(list3, list4)
	fmt.Println(ret)
}

结果如下:

分析

时间复杂度:O(max(len(nums1), len(nums2)))

空间复杂度:O(max(len(nums1), len(nums2)))