leetcode算法:2.两数相加

两数相加

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

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

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

示例:

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

思考

这题比较方便的是给定的两个链表已经是从个位开始的,不需要我们再去找到最低位。 有两个需要注意的地方:

  • 第一个是长短不一的链表是要一直处理到最长那个结束的,而不是最短链表
  • 第二个需要注意的地方是最高位之和可能会导致进位,此时可能需要新增一个节点,如 753+864 中 7+8导致的进位

解答

  • 时间复杂度: O(max(list1, list2)),因为处理的次数取决于最长的那个链表
  • 空间复杂度: O(max(list1, list2)),新列表的长度最多为max(list1, list2)+1,因为最高位可能导致进位
package algo

type ListNode struct {
	Val  int
	Next *ListNode
}

func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
	// 存在一个空list时无意义
	if l1 == nil || l2 == nil {
		return nil
	}

	var (
		sumList     = &ListNode{}
		currentNode = sumList
		nextL1      = l1
		nextL2      = l2
		carry       = 0 //进位值
	)

	for nextL1 != nil || nextL2 != nil {
		var sum, x, y int

		if nextL1 != nil {
			x = nextL1.Val
			nextL1 = nextL1.Next
		} else {
			x = 0
		}

		if nextL2 != nil {
			y = nextL2.Val
			nextL2 = nextL2.Next
		} else {
			y = 0
		}

		sum = x + y + carry
		carry = sum / 10

		// 不要使用 currentNode.Val = sum % 10; currentNode.Next = &ListNode{};
		// 否则会导致最后多余一个ListNode{}结点
		currentNode.Next = &ListNode{Val: sum % 10}
		currentNode = currentNode.Next

	}

	// 最高位相加导致的进位,如 753+864 中 7+8导致的进位
	if carry > 0 {
		currentNode.Next = &ListNode{Val: carry}
	}

	return sumList.Next
}

  

单元测试:

package algo

import (
	"math/rand"
	"strings"
	"testing"
)

func TestTwoNumbers(t *testing.T) {
	linkList1 := makeList()
	linkList2 := makeList()

	res := addTwoNumbers(linkList1, linkList2)
	if res == nil {
		t.Fatal("empty result")
	}

	print("第一链表: ")
	traverse(linkList1)

	print("第二链表: ")
	traverse(linkList2)

	print("结果链表: ")
	traverse(res)

	println(strings.Repeat("=", 30))

	sameList := makeList()
	res = addTwoNumbers(sameList, sameList)
	if res == nil {
		t.Fatal("empty result")
	}

	print("同一链表: ")
	traverse(sameList)

	print("结果链表: ")
	traverse(res)
}

// 创建单链表
func makeList() *ListNode {
	var listNode = &ListNode{Val: rand.Intn(9) + 1}
	cnt := rand.Intn(6) + 3
	for i := 1; i < cnt; i++ {
		l := listNode
		for {
			if l.Next == nil {
				l.Next = &ListNode{Val: rand.Intn(9) + 1}
				break
			}
			l = l.Next
		}
	}
	return listNode
}

// 遍历单链表
func traverse(linkList *ListNode) {
	iter := linkList
	for {
		if iter != nil {
			if iter.Next == nil {
				print(iter.Val)
			} else {
				print(iter.Val, "->")
			}
			iter = iter.Next
		} else {
			break
		}
	}
	println()
}

  

posted @ 2020-07-15 21:47  impluse  阅读(266)  评论(0编辑  收藏  举报