代码随想录day13|102层序遍历226翻转二叉树101对称二叉树|01笔记

77 阅读2分钟
  • 层序遍历

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 层序遍历的实现就是需要一个容器,每次存储二叉树一层的节点。每遍历完当前层节点的数值之后,再获得下一层的结点。
  • 解题代码

  • 迭代法
  •     /**
         * Definition for a binary tree node.
         * type TreeNode struct {
         *     Val int
         *     Left *TreeNode
         *     Right *TreeNode
         * }
         */
        func levelOrder(root *TreeNode) [][]int {
            ans := make([][]int,0)
            if root == nil{//防止为空
                return ans
            }
            layer := []int{}
            listT := list.New()
            listT.PushBack(root)
        
            for listT.Len()!=0 {
                layer = []int{}
                len := listT.Len()
                for i:=0;i<len;i++ {
                    node := listT.Remove(listT.Front()).(*TreeNode)
                    if node.Left != nil {
                        listT.PushBack(node.Left)
                    }
                    if node.Right != nil {
                        listT.PushBack(node.Right)
                    }
                    layer = append(layer, node.Val)
                }
                ans = append(ans, layer)
                
            }
            return ans
        }
        /**
        102. 二叉树的层序遍历:使用切片模拟队列,易理解
         */
        func levelOrder(root *TreeNode) (res [][]int) {
            if root == nil {
                return
            }
        
            curLevel := []*TreeNode{root}  // 存放当前层节点
            for len(curLevel) > 0 {
                nextLevel := []*TreeNode{}  // 准备通过当前层生成下一层
                vals := []int{}
        
                for _, node := range curLevel {
                    vals = append(vals, node.Val) // 收集当前层的值
                    // 收集下一层的节点
                    if node.Left != nil {
                        nextLevel = append(nextLevel, node.Left)
                    }
                    if node.Right != nil {
                        nextLevel = append(nextLevel, node.Right)
                    }
                }
                res = append(res, vals)
                curLevel = nextLevel // 将下一层变成当前层
            }
        
            return
        }
    
  • 递归法:
  • 定义深度值depth用以控制每层数组的添加。
  •     /**
        102. 二叉树的递归遍历
         */
        func levelOrder(root *TreeNode) [][]int {
        	arr := [][]int{}
        
        	depth := 0
        
        	var order func(root *TreeNode, depth int)
        
        	order = func(root *TreeNode, depth int) {
        		if root == nil {
        			return
        		}
        		if len(arr) == depth {
        			arr = append(arr, []int{})
        		}
        		arr[depth] = append(arr[depth], root.Val)
        
        		order(root.Left, depth+1)
        		order(root.Right, depth+1)
        	}
        
        	order(root, depth)
        
        	return arr
        }
    
  • 226翻转二叉树

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 只需要遍历每一个节点然后把左右指针交换即可,深搜和宽搜都可以实现。要主意中序遍历会把一个节点翻转两次。
  • 解题代码

  • 递归前序
  •     func invertTree(root *TreeNode) *TreeNode {
            if root == nil {
                return nil
            }
            root.Left, root.Right = root.Right, root.Left    //交换
            
            invertTree(root.Left)
            invertTree(root.Right)
        
            return root
        }
    
  • 递归后序
  •     func invertTree(root *TreeNode) *TreeNode {
            if root == nil {
                return root
            }
            
            invertTree(root.Left)     //遍历左节点
            invertTree(root.Right)    //遍历右节点
            root.Left, root.Right = root.Right, root.Left    //交换
            
            return root
        }
    
  • 迭代前序
  •     func invertTree(root *TreeNode) *TreeNode {
            stack := []*TreeNode{}
            node := root
            for node != nil || len(stack) > 0 {
                for node != nil {
                    node.Left, node.Right = node.Right, node.Left    //交换
                    stack = append(stack,node)
                    node = node.Left
                }
                node = stack[len(stack)-1]
                stack = stack[:len(stack)-1]
                node = node.Right
            }
            
            return root
        }
    
  • 迭代后序
  •     func invertTree(root *TreeNode) *TreeNode {
            stack := []*TreeNode{}
            node := root
            var prev *TreeNode
            for node != nil || len(stack) > 0 {
                for node != nil {
                    stack = append(stack, node)
                    node = node.Left
                }
                node = stack[len(stack)-1]
                stack = stack[:len(stack)-1]
                if node.Right == nil || node.Right == prev {
                    node.Left, node.Right = node.Right, node.Left     //交换
                    prev = node
                    node = nil
                } else {
                    stack = append(stack, node)
                    node = node.Right
                }
            }
            
            return root
        }
    
  • 层序
  •     func invertTree(root *TreeNode) *TreeNode {
            if root == nil{
                return root
            }
            queue := list.New()
            node := root
            queue.PushBack(node)
            for queue.Len() > 0 {
                length := queue.Len()
                for i := 0; i < length; i++ {
                    e := queue.Remove(queue.Front()).(*TreeNode)
                    e.Left, e.Right = e.Right, e.Left    //交换
                    if e.Left != nil {
                        queue.PushBack(e.Left)
                    }
                    if e.Right != nil {
                        queue.PushBack(e.Right)
                    }
                }
            }
            return root
        }
    
  • 101对称二叉树

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 刚做完翻转二叉树,猜测对侧二叉树经过翻转之后会与本身一致,可以用此检验。但这个方法比较繁琐,也许有更好的方式。
  • 讲解观后感

  • 判断二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转。但要注意遍历的方法应该对称,选择后序遍历的左右中和右左中。必须按照遍历顺序依次直接比较。若通过两次遍历存储节点的方式来进行比较,可能产生树形结构不同但存储顺序相同的情况。
  • 解题代码

  • 递归dfs
  •     /**
         * Definition for a binary tree node.
         * type TreeNode struct {
         *     Val int
         *     Left *TreeNode
         *     Right *TreeNode
         * }
         */
        func isSymmetric(root *TreeNode) bool {
            if root==nil {
                return false
            }
            return compare(root.Left, root.Right)
        }
        
        func compare(left *TreeNode, right *TreeNode) bool{
            if left==nil && right==nil {
                return true
            }
            if left == nil || right == nil {
                return false;
            };
            if left.Val != right.Val {
                return false;
            } 
            return compare(left.Left, right.Right) && compare(left.Right, right.Left)
        }
    
  • 迭代(利用队列(切片))
  •     // 迭代
        func isSymmetric(root *TreeNode) bool {
            var queue []*TreeNode;
            if root != nil {
                queue = append(queue, root.Left, root.Right);
            }
            for len(queue) > 0 {
                left := queue[0];
                right := queue[1];
                queue = queue[2:];
                if left == nil && right == nil {
                    continue;
                }
                if left == nil || right == nil || left.Val != right.Val {
                    return false;
                };
                queue = append(queue, left.Left, right.Right, right.Left, left.Right);
            }
            return true;
        }