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 // 出現一側節點不為空的情況,此時不是滿二叉樹
}