代码随想录day15 || 110 平衡二叉树,257 二叉树所有路径,404 左叶子之和,222 完全二叉树节点个数
110 平衡二叉树
// 计算平衡二叉树,定义,左右子树高度差不超过1,然后考虑计算高度,计算高度通常使用从叶子节点递归向上传递高度计算,也就是后续遍历的方式
func isBalanced(root *TreeNode) bool {
// 思路 后续遍历同时求左右子树的高度,如果左右子树的高度差大于1,返回-1
return !(getHigh(root) == -1)
}
func getHigh(root *TreeNode) int {
// 根节点高度为0
if root == nil {
return 0
}
// 后序遍历计算高度
//左
left := getHigh(root.Left)
if left == -1{
return -1
}
//右
right := getHigh(root.Right)
if right == -1{
return -1
}
// 根
if left - right > 1 || right - left > 1{ // 如果高度差>1 返回-1
return -1
}
var max int
if left > right {
max = left
}else {
max = right
}
return max+1 // 此时的根节点高度
}
// 时间复杂度 每个节点都遍历一次n 空间复杂度logn
257 二叉树所有路+
思路: 层序遍历最简单暴力求出每一层的节点,然后遍历每一层,strings.join(), 这样理论最大时间复杂度是2^0 * 2^1 ... 2^dep = 2^(0+1+2+...+dep) 非常复杂, 但是可以简化
func binaryTreePaths(root *TreeNode) []string {
// 层序遍历
q := list.New()
q.PushBack(&NodePath{Node: root, Path: strconv.Itoa(root.Val)})
var res []string
for q.Len() > 0 {
nodePath := q.Remove(q.Front()).(*NodePath)
node := nodePath.Node
path := nodePath.Path
// 如果是叶子节点,保存路径
if node.Left == nil && node.Right == nil {
res = append(res, path)
}
// 如果有左子节点,加入队列并更新路径
if node.Left != nil {
newPath := join(path ,node.Left.Val)
q.PushBack(&NodePath{Node: node.Left, Path: newPath})
}
// 如果有右子节点,加入队列并更新路径
if node.Right != nil {
newPath := join(path ,node.Right.Val)
q.PushBack(&NodePath{Node: node.Right, Path: newPath})
}
}
return res
}
type NodePath struct {
Node *TreeNode
Path string
}
func join(s1 string, i2 int) string {
s2 := strconv.Itoa(i2)
var s strings.Builder
s.WriteString(s1)
s.WriteString("->")
s.WriteString(s2)
return s.String()
}
func binaryTreePaths(root *TreeNode) []string {
// 递归回溯算法
var res = &[]string{}
var q = &[]int{}
traversal(root, res, q)
return *res
}
func traversal(root *TreeNode, res *[]string, q *[]int) {
// mid
*q = append(*q, root.Val)
if root.Left == nil && root.Right == nil {
fmt.Println("nil")
*res = append(*res, join(q))
}
// left
if root.Left != nil {
traversal(root.Left, res, q)
*q = (*q)[0 : len(*q)-1] // 回溯移除最后一个节点
}
//right
if root.Right != nil {
traversal(root.Right, res, q)
*q = (*q)[0 : len(*q)-1]
}
}
func join(q *[]int) string {
var res []string
for _, i := range *q{
s := strconv.Itoa(i)
res = append(res, s)
}
return strings.Join(res, "->")
}
404 左 叶子 和
func sumOfLeftLeaves(root *TreeNode) int {
// 最简单思路层序遍历,遇到左节点,返回
var sum int
q := list.New()
q.PushBack(root)
for q.Len() > 0 {
node := q.Remove(q.Front()).(*TreeNode)
if node.Left != nil {
if node.Left.Left == nil && node.Left.Right == nil { // 判断叶子节点
sum += node.Left.Val
}
q.PushBack(node.Left)
}
if node.Right != nil {
q.PushBack(node.Right)
}
}
return sum
}
时间n 空间n
func sumOfLeftLeaves(root *TreeNode) int {
// 递归参数返回值,参数为节点,返回值为当前节点的左叶子和
// 递归终止条件:如果节点为空,返回0
if root == nil {
return 0
}
// 初始化左子树和右子树的左叶子节点和
leftSum := 0
rightSum := 0
// 如果左子节点存在并且是叶子节点,直接返回左子节点的值
if root.Left != nil && root.Left.Left == nil && root.Left.Right == nil {
leftSum = root.Left.Val
} else {
// 否则递归计算左子树的左叶子节点和
leftSum = sumOfLeftLeaves(root.Left)
}
// 递归计算右子树的左叶子节点和
rightSum = sumOfLeftLeaves(root.Right)
// 返回左子树和右子树的左叶子节点和
return leftSum + rightSum
}
222 完全二叉树节点个数
func countNodes(root *TreeNode) int {
// 思路 遍历查数
var res []int
traversal(root, &res)
return len(res)
}
func traversal(root *TreeNode, res *[]int) {
if root == nil {
return
}
*res = append(*res, root.Val)
traversal(root.Left, res)
traversal(root.Right, res)
}
func countNodes(root *TreeNode) int {
// 利用满二叉树特性思路,题设完全二叉树,所以通过判断root是不是满二叉树,如果是直接2^n - 1, 如果不是,判断左右子节点,然后相加
// 递归终止,判断为满二叉树
if root == nil {
return 0
}
var left, right int
dep := checkFull(root)
if dep == -1 { // 判断左子树是否是满二叉树
left = countNodes(root.Left)
right = countNodes(root.Right)
}else{
return int(math.Pow(2, float64(dep))) - 1
}
fmt.Println(root, left, right)
return left + right + 1
}
// 判断是否是满二叉树,并且返回层数
func checkFull (root *TreeNode) int {
if root == nil {
return -1
}
if root.Left == nil && root.Right == nil {
return 1
}
left := root.Left
right := root.Right
dep := 1
for left != nil && right != nil{
left = left.Left
right = right.Right
dep += 1
if left == nil && right == nil { // 同时遍历到终点,说明是满二叉树
return dep
}
}
return -1 // 出现一侧节点不为空的情况,此时不是满二叉树
}

浙公网安备 33010602011771号