代码随想录 day15 第六章 二叉树part02

今日内容:

●  层序遍历  10

●  226.翻转二叉树

●  101.对称二叉树 2

1. 层序遍历

关联 leetcode

102.二叉树的层序遍历

107.二叉树的层次遍历II 199.二叉树的右视图 637.二叉树的层平均值 429.N叉树的层序遍历 515.在每个树行中找最大值 116.填充每个节点的下一个右侧节点指针 117.填充每个节点的下一个右侧节点指针II 104.二叉树的最大深度 111.二叉树的最小深度

  • 相当于图论的广度优先搜索
    • 按照层序来输出当前层的所有元素
  • 二叉树本身这个结构无法做到层序遍历
    • 需要借助额外数据结构:队列
      • 存储每一层遍历过的元素
  • 题解
    • 102.二叉树的层序遍历
      • 个人解法:

        • 两个数组:当前层节点数组+子节点数组

          type TreeNode struct {
                Val int
                Left *TreeNode
                Right *TreeNode
            }
           /
          func levelOrder(root *TreeNode) [][]int {
          	rets := make([][]int, 0)// 最终结果
          	if root == nil {
          		return rets
          	}
          	curNodes := make([]*TreeNode, 0)//当前层节点
          	curNodes = append(curNodes, root)//初始化放入root节点
          	sonNodes := make([]*TreeNode, 0)//当前层节点的子节点
          	ret := make([]int, 0)//存储当前节点值的数组
          
          LeverLoop:
          	for _, node := range curNodes {//遍历当前层所有节点
          		ret = append(ret, node.Val)//按序存储当前层节点值
          		//添加当前节点的非空子节点【左右有序】
          		if node.Left != nil {
          			sonNodes = append(sonNodes, node.Left)
          		}
          		if node.Right != nil {
          			sonNodes = append(sonNodes, node.Right)
          		}
          	}
          	rets = append(rets, ret)//存储当前层节点值
          	if len(sonNodes) != 0 {//当前层还有子节点存在
          		curNodes = sonNodes//继续遍历子节点层
          		sonNodes = make([]*TreeNode, 0)//初始化子节点
          		ret = make([]int, 0)//初始化当前层节点值
          		goto LeverLoop//继续循环遍历
          	}
          	return rets
          }
          
          /*不用 goto*/
          func levelOrder(root *TreeNode) [][]int {
          	rets := make([][]int, 0)
          	if root == nil {
          		return rets
          	}
          	curNodes := make([]*TreeNode, 0)
          	curNodes = append(curNodes, root)
          
          	for len(curNodes) > 0 {
          		ret := make([]int, 0)
          		sonNodes := make([]*TreeNode, 0)
          		for _, node := range curNodes {
          			ret = append(ret, node.Val)
          			if node.Left != nil {
          				sonNodes = append(sonNodes, node.Left)
          			}
          			if node.Right != nil {
          				sonNodes = append(sonNodes, node.Right)
          			}
          		}
          		rets = append(rets, ret)
          		curNodes = sonNodes
          	}
          	return rets
          }
          
      • 卡哥讲解解法:

        • 一个数组实现

          func levelOrder(root *TreeNode) [][]int {
          	rets := [][]int{}
          	if root == nil { //防止为空
          		return rets
          	}
          	
          	//用链表实现队列, 队尾进, 队首出
          	queue := list.New()
          	queue.PushBack(root)
          
          	ret := make([]int, 0)
          
          	for queue.Len() > 0 {
          		length := queue.Len() //保存当前层的长度,然后处理当前层(十分重要,防止添加下层元素影响判断层中元素的个数)
          		for i := 0; i < length; i++ {
          			node := queue.Remove(queue.Front()).(*TreeNode) //出队列
          			if node.Left != nil {
          				queue.PushBack(node.Left)
          			}
          			if node.Right != nil {
          				queue.PushBack(node.Right)
          			}
          			ret = append(ret, node.Val) //将值加入本层切片中
          		}
          		rets = append(rets, ret) //放入结果集
          		ret = []int{}            //清空层的数据
          	}
          
          	return rets
          }
          

2. 翻转二叉树 (优先掌握递归)

关联 leetcode 226.翻转二叉树

  • 左右翻转的是节点本身【即是指针而不简单是交换数值】
  • 有个个人思路:
    • 用上一道的广度搜索【把空指针一期加进去】,然后遍历结果数值,分配左右孩子
  • 这道用 递归前序、后序最直接
    1. 确定返回值
    2. 确定终止条件
    3. 处理逻辑
  • 题解【递归遍历二叉树】
    • 前序:中左右

      func invertTree(root *TreeNode) *TreeNode {
      	if root == nil {
      		return root
      	}
      	node := root
      	//前序遍历: 中左右
      	//每次都交换当前节点的左右节点
      	node.Right, node.Left = node.Left, node.Right
      	invertTree(node.Left)
      	invertTree(node.Right)
      	return root
      }
      
    • 后序:左右中

      func invertTree(root *TreeNode) *TreeNode {
      	if root == nil {
      		return root
      	}
      	node := root
      	//后序遍历: 左右中
      	//每次都交换当前节点的左右节点
      	invertTree(node.Left)
      	invertTree(node.Right)
      	node.Right, node.Left = node.Left, node.Right
      	return root
      }
      
      

3. 对称二叉树(优先掌握递归)

关联 leetcode 101. 对称二叉树

  • 递归只能使用后序
    • 后序:左右中
    • 解题思路:
      • 收集左右孩子节点 —返回—> 上一个节点
    • 比较:
      • 左右孩子的外侧节点
        • 左孩子的左节点,右孩子的右节点
      • 左右孩子的内侧节点
        • 左孩子的右节点,右孩子的左节点
  • 题解
    • 递归法

      type TreeNode struct {
      	Val int
      	Left *TreeNode
      	Right *TreeNode
      }
      func compare(left, right *TreeNode) bool {
      	/*比较两个节点自身*/
      	if left == nil && right != nil {
      		return false
      	}
      	if right == nil && left != nil {
      		return false
      	}
      	if right == nil && left == nil {
      		return true
      	}
      	// left != nil && right != nil
      	// 需要比较节点的数值了
      	if left.Val != right.Val {
      		return false
      	}
      	//	比较左右节点的外侧节点,内侧节点
      	outRes := compare(left.Left, right.Right)
      	insideRes := compare(left.Right, right.Left)
      	return insideRes && outRes
      }
      func isSymmetric(root *TreeNode) bool {
      	if root == nil {
      		return true
      	}
      	return compare(root.Left, root.Right)
      }
      
    • 迭代法

      • 自己构造一个栈
      • 待比较的节点两两一组,互相配对

  • 18
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值