代码随想录算法训练营|day18
513.找树左下角的值
(1)递归:复用求最大深度
先递归遍历左子树,后右子树,所以当取到最大深度时,返回对应的节点值
func findBottomLeftValue(root *TreeNode) int {
if root == nil {
return 0
}
height := 0
leftVal := 0
var getDepth func(root *TreeNode, depth int)
getDepth = func(root *TreeNode, depth int) {
if root == nil {
return
}
depth++
getDepth(root.Left, depth)
getDepth(root.Right, depth)
if depth > height {
height = depth
leftVal = root.Val
}
}
getDepth(root, 0)
return leftVal
}
(2)迭代:最后一层第一个值
func findBottomLeftValue(root *TreeNode) int {
if root == nil {
return 0
}
queue := []*TreeNode{root}
res := 0
for len(queue) > 0 {
size := len(queue)
for i:= 0; i < size; i++ {
node := queue[0]
if i == 0 {
res = node.Val
}
queue = queue[1:]
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue,node.Right)
}
}
}
return res
}
112.路径总和
求二叉树所有路径的变体
(1)递归:递归判断当前节点到叶子节点之和是否为targetSum
func hasPathSum(root *TreeNode, targetSum int) bool {
if root == nil {
return false
}
if root.Left == nil && root.Right == nil {
return targetSum == root.Val
}
return hasPathSum(root.Left, targetSum - root.Val) || hasPathSum(root.Right, targetSum - root.Val)
}
(2)层序遍历:nodeQueue存储了根节点到包括当前节点的所有节点,sumQueue记录了根节点到该节点之和
func hasPathSum(root *TreeNode, targetSum int) bool {
if root == nil {
return false
}
nodeQueue := []*TreeNode{root}
sumQueue := []int{root.Val}
for i := 0; i < len(nodeQueue); i++ {
node, sum := nodeQueue[i], sumQueue[i]
if node.Left == nil && node.Right == nil {
if sum == targetSum {
return true
}
continue
}
if node.Left != nil {
nodeQueue = append(nodeQueue, node.Left)
sumQueue = append(sumQueue, sum + node.Left.Val)
}
if node.Right != nil {
nodeQueue = append(nodeQueue, node.Right)
sumQueue = append(sumQueue, sum + node.Right.Val)
}
}
return false
}
113.路径总和ii
(1)递归:初始化记录路径;终止条件;递归左右子树
func pathSum(root *TreeNode, targetSum int) [][]int {
res := make([][]int, 0)
path := []int{}
var help func(root *TreeNode, targetSum int)
help = func(root *TreeNode, targetSum int) {
if root == nil {
return
}
path = append(path, root.Val)
targetSum -= root.Val
if root.Left == nil && root.Right == nil && targetSum == 0{
res = append(res, path)
}
help(root.Left, targetSum)
help(root.Right, targetSum)
}
help(root, targetSum)
return res
}
(2)层序遍历:
遍历时对path变量使用append方法,会修改底层数组,进而会影响到pathQueue中的其它路径。需要为每个路径创建一个新的切片副本。
type group struct {
Node *TreeNode
Val []int
}
func pathSum(root *TreeNode, targetSum int) [][]int {
var res [][]int
if root == nil {
return res
}
queue := []*group{{root, []int{root.Val}}}
for len(queue) > 0 {
node := queue[0].Node
valArr := queue[0].Val
queue = queue[1:]
sum := 0
for _, val := range valArr {
sum += val
}
if node.Left == nil && node.Right == nil && sum == targetSum {
res = append(res, valArr)
}
valArrCp := make([]int, len(valArr))
copy(valArrCp, valArr)
if node.Left != nil {
valArr1 := valArrCp
valArr1 = append(valArr1, node.Left.Val)
queue = append(queue, &group{node.Left, valArr1})
}
if node.Right != nil {
valArr2 := valArrCp
valArr2 = append(valArr2, node.Right.Val)
queue = append(queue, &group{node.Right, valArr2})
}
}
return res
}
106.从中序与后序遍历序列构造二叉树
(1)递归:找到后序数组中最后一个元素在中序数组中的位置。递归右子树和左子树
func buildTree(inorder []int, postorder []int) *TreeNode {
var build func(inorderLeft, inorderRight int) *TreeNode
build = func(inorderLeft, inorderRight int) *TreeNode {
if inorderLeft > inorderRight {
return nil
}
rootVal := postorder[len(postorder) - 1]
postorder = postorder[:len(postorder) - 1]
root := &TreeNode{Val:rootVal}
i := 0
for i = 0; i < len(inorder); i++ {
if inorder[i] == rootVal {
break
}
}
root.Right = build(i + 1, inorderRight)
root.Left = build(inorderLeft, i - 1)
return root
}
return build(0, len(inorder) - 1)
}
105.从前序与中序遍历序列构造二叉树
(1)递归:找到前序数组中第一个元素在中序数组中的位置。递归左子树和右子树
func buildTree(preorder []int, inorder []int) *TreeNode {
var build func(inorderLeft, inorderRight int) *TreeNode
build = func(inorderLeft, inorderRight int) *TreeNode{
if inorderLeft > inorderRight {
return nil
}
rootVal := preorder[0]
root := &TreeNode{Val : rootVal}
preorder = preorder[1:]
i := 0
for i = 0; i < len(inorder); i++ {
if inorder[i] == rootVal {
break
}
}
root.Left = build(inorderLeft, i - 1)
root.Right = build(i + 1, inorderRight)
return root
}
return build(0, len(inorder) - 1)
}
代码随想录文章详解
513.找树左下角的值
112.路径总和 | 113.路径总和ii
106.从中序与后序遍历序列构造二叉树 | 105.从前序与中序遍历序列构造二叉树
总结
递归求解通常需要公共变量提取,创建无返回值函数,或者返回值为bool
注意切片扩容,导致结果出错,切片深拷贝、浅拷贝
感谢代码随想录练习营大佬们的帮助和解答