代码随想录算法训练营|day15二叉树相关推荐

本文介绍了多个二叉树和N叉树相关的算法问题,包括层次遍历、右视图、层平均值计算,以及在每个树行中找最大值。涉及递归和迭代两种解法,展示了如何通过这两种方式解决这些问题。
摘要由CSDN通过智能技术生成

107.二叉树的层次遍历II

切片本质是一个结构体,包含一个指向底层数组的指针(prt),长度(len),容量(cap)。如果通过函数对切片进行赋值,修改会传递到函数外;但如果在函数内对切片进行扩容,会产生新的底层数组,但数组外的切片仍指向原来的旧切片,进而导致对切片的修改无法传递到函数外
(1)递归

func levelOrderBottom(root *TreeNode) [][]int {
    res := [][]int{}
    var help func(root *TreeNode, depth int) 
    help = func(root *TreeNode, depth int) {
        if root == nil {
            return
        }
        if depth == len(res) {
            res = append(res, []int{})
        }
        res[depth] = append(res[depth], root.Val)
        depth++
        help(root.Left, depth)
        help(root.Right, depth)
    } 
    help(root, 0)
    
    for i, j := 0, len(res) - 1; i < j; i, j = i + 1, j - 1 {
        res[i], res[j] = res[j], res[i]
    }
    return res
}

(2)层序

func levelOrderBottom(root *TreeNode) [][]int {
    res := [][]int{}
    if root == nil {
        return res
    }
    node := root
    queue := []*TreeNode{root}
    for len(queue) > 0 {
        size := len(queue)
        vals := []int{}
        for i := 0; i < size; i++ {
            node = queue[0]
            queue = queue[1:]
            vals = append(vals, node.Val)
            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
        // 反向插入结果
        res = append(res, []int{})
        copy(res[1:], res[0:])
        res[0] = vals
    }
    return res
}

199.二叉树的右视图

(1)递归
中—>右—>左顺序访问,保证了每层最先访问的是最右边节点
如果当前节点的高度等于len(res),将其值加入res。当前节点类似于为res扩张探路。

func rightSideView(root *TreeNode) []int {
    res := []int{}
    var help func(root *TreeNode, depth int)
    help = func(root *TreeNode, depth int) {
        if root == nil {
            return
        }
        if depth == len(res) {
            res = append(res, root.Val)
        }
        depth++
        help(root.Right, depth)
        help(root.Left, depth)
    }
    help(root, 0)
    return res
}

(2)层序

func rightSideView(root *TreeNode) []int {
    res := []int{}
    if root == nil {
        return res
    }
    curQueue := []*TreeNode{root}
    for len(curQueue) > 0 {
        nextQueue := []*TreeNode{}
        size := len(curQueue)
        for i := 0; i < size; i++ {
            node := curQueue[i]
            if node.Left != nil {
                nextQueue = append(nextQueue, node.Left)
            }
            if node.Right != nil {
                nextQueue = append(nextQueue, node.Right)
            }
            if i == size - 1 {
                res = append(res, node.Val)
            }
        }
        curQueue = nextQueue
    }
    return res
}

637.二叉树的层平均值

(1)递归
创建结构体nodeGroup,存储当前层node个数sum
类似上题解法:若当前节点高度小于len(nodeGroup),对当前层nodeGroup的count和sum进行更新【count+=1,sum+=root.val】;若当前节点高度等于len(nodeGroup),创建新的层,并对count和sum赋值【count=1,sum=root.val】。

type nodeGroup struct {
	Count int
	sum   int
}

func averageOfLevels(root *TreeNode) []float64 {
	res := []float64{}
	resGroup := []nodeGroup{{0, 0}}
	var help func(root *TreeNode, depth int)
	help = func(root *TreeNode, depth int) {
		if root == nil {
			return
		}
		if depth < len(resGroup) {
			resGroup[depth].Count++
			resGroup[depth].sum += root.Val
		} else {
			resGroup = append(resGroup, nodeGroup{1, root.Val})
		}
		depth++
		help(root.Left, depth)
		help(root.Right, depth)
	}
	help(root, 0)
	for _, countSum := range resGroup {
		avg := float64(countSum.sum) / float64(countSum.Count)
		res = append(res, avg)
	}
	return res
}

(2)层序

func averageOfLevels(root *TreeNode) []float64 {
	res := []float64{}
	curQueue := []*TreeNode{root}
	for len(curQueue) > 0 {
		size := len(curQueue)
		sum := 0
		nextQueue := []*TreeNode{}
		for _, node := range curQueue {
			sum += node.Val
			if node.Left != nil {
				nextQueue = append(nextQueue, node.Left)
			}
			if node.Right != nil {
				nextQueue = append(nextQueue, node.Right)
			}
		}
		res = append(res, float64(sum)/float64(size))
		curQueue = nextQueue
	}
	return res
}

429.N叉树的层序遍历

(1)递归:追加当前层数据,如果当前节点高度等于len(res),创建新层。

func levelOrder(root *Node) [][]int {
    res := [][]int{}
    var help func(root *Node, depth int)
    help = func(root *Node, depth int) {
        if root == nil {
            return 
        }
        if depth == len(res) {
            res = append(res, []int{})
        }
        res[depth] = append(res[depth], root.Val)
        depth++
        for _, child := range root.Children {
            help(child, depth)
        }
    }
    help(root, 0)
    return res
}

(2)迭代:创建新层,追加数据。

func levelOrder(root *Node) [][]int {
    res := [][]int{}
    if root == nil {
        return res
    }
    curQueue := []*Node{root}
    depth := 0
    for len(curQueue) > 0 {
        nextQueue := []*Node{}
        res = append(res, []int{})
        for _, node := range curQueue {
            res[depth] = append(res[depth], node.Val)
            for _, child := range node.Children {
                nextQueue = append(nextQueue, child)
            }
        }
        depth++
        curQueue = nextQueue
    }
    return res
}

515.在每个树行中找最大值

(1)递归

func largestValues(root *TreeNode) []int {
    res := []int{}
    var help func(root *TreeNode, depth int) 
    help = func(root *TreeNode, depth int) {
        if root == nil {
            return
        }
        if depth == len(res) {
            res = append(res, root.Val)
        }
        if root.Val > res[depth] {
            res[depth] = root.Val
        }
        depth++
        help(root.Left, depth)
        help(root.Right,depth)
        return
    }
    help(root, 0)
    return res
}

(2)迭代

func largestValues(root *TreeNode) []int {
    res := []int{}
    if root == nil {
        return res
    }
    depth := 0
    curQueue := []*TreeNode{root}
    for len(curQueue) > 0 {
        nextQueue := []*TreeNode{}
        for _, node := range curQueue {
            if depth == len(res) {
                res = append(res, node.Val)
            }
            if node.Val > res[depth] {
                res[depth] = node.Val
            }
            if node.Left != nil {
                nextQueue = append(nextQueue, node.Left)
            }
            if node.Right != nil {
                nextQueue = append(nextQueue, node.Right)
            }
        }
        depth++
        curQueue = nextQueue
    }
    return res
}

116.填充每个节点的下一个右侧节点指针

(1)递归:如果当前节点高度等于len(res),证明该节点是最新一层最左侧节点,将其追加到res中;否则将res[depth]节点指向当前节点,并更新res[depth]当前节点

func connect(root *Node) *Node {
    res := []*Node{}
    var help func(root *Node, depth int) 
    help = func (root *Node, depth int) {
        if root == nil {
            return
        }
        if depth == len(res) {
            res = append(res, root)
        } else {
            res[depth].Next = root
            res[depth] = root
        }
        depth++
        help(root.Left, depth)
        help(root.Right, depth)
    }
    help(root, 0)
    return root
}

(2)迭代

func connect(root *Node) *Node {
    if root == nil {
        return root
    }
    curQueue := []*Node{root}
    for len(curQueue) > 0 {
        nextQueue := []*Node{}
        size := len(curQueue)
        for i := 0; i < size; i++ {
            node := curQueue[i]
            if node.Left != nil {
                nextQueue = append(nextQueue, node.Left)
            }
            if node.Right != nil {
                nextQueue = append(nextQueue, node.Right)
            }
            if i == size - 1 {
                break
            }
            node.Next = curQueue[i + 1]
        }
        curQueue = nextQueue
    }
    return root
}

117.填充每个节点的下一个右侧节点指针II

题解:只能说与上题一模一样

总结

树,递归,层序迭代一个套路走完所有题
大佬递归方法太秀了!必须码住

代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值