LeetCode算法之--二叉树系列

点赞收藏,以防遗忘

本文【程序大视界】已收录,关注免费领取互联网大厂学习资料,添加博主好友进群学习交流,欢迎留言和评论,一起交流共同进步。

目录

【一】前言

【二】二叉树的最大深度

【三】二叉树的遍历

【四】总结


【一】前言

二叉树也是面试算法的常见题型,通常程序会自定义树节点,需要我们实现如找出深度、遍历等。

【二】二叉树的最大深度

104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:
给定二叉树 [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

解法一】深度优先:新建一个result集合用于保存并返回结果集合,边界条件为root为null,则返回result,递归方法开始传入root和levle为0层,依次递增层数并新建结果集合里的子集list,结果集合中添加该节点的值val,并递归遍历该节点的左子树和右子树,直至递归遍历完该二叉树的所有节点,返回的result结果集合就是所求。

class Solution {
   List<List<Integer>> result = new ArrayList<List<Integer>>();
   public List<List<Integer>> levelOrder(TreeNode root) {
     If(root == null){
       return result ;
     }
     dfs(root,0);
     return result;
   }
   public void dfs(TreeNode root,int level){
     //递归终止条件
     If(root  == null){
        return ;
     } 
     If( result.size == level){
        result.add(New ArrayList<Integer>());
     }
     result.get(level).add(root.val);
     dfs(root.left,level+1);
     dfs(root.right,level+1);
   }
}

解法二】广度优先:新建一个result集合用于保存和返回结果集合,边界条件当root为空,则直接返回结果集。建队列queue保存root根节点,按照每一层左、右子树的顺序,一次访问二叉树的节点,遍历每一层的节点时用一个list集合把该层的所有节点从左到右顺序保存起来,遍历完每一层把list集合添加到结果集合中,遍历完所有层,result结果集合就是要求的答案。

class Solution {
   public List<List<Integer>> levelOrder(TreeNode root) {
     List<List<Integer>> result = new ArrayList<List<Integer>>();
     If(root == null){
       return result ;
     }
     Queue<TreeNode> queue = new LinkedList<TreeNode>();
     queue.offer(root);
     While(!queue.isEmpty()){
       Int size = queue.size();
       List<Integer> list = new ArrayList<Integer>();
 	   While(size >0){
         TreeNode node = queue.poll();
         list .add(node.val);
         If(node.left != null){
  	       queue.offer(node.left);
         }
         If(node.right != null){
  		   queue.offer(node.right);
         }
         size --;
       }
       result.add(list); 
     }
    return result ;
  }
}

【三】二叉树的遍历

94. 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

示例 1:

输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

提示:

  • 树中节点数目在范围 [0, 100] 内
  • -100 <= Node.val <= 100

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

解法一】迭代解决:新建一个List集合用以存放结果返回集合,新建一个Deque双端队列用作遍历二叉树出入栈使用,当root或stack不为空时,遍历二叉树,一直遍历到左子树为空时,从栈弹出节点并把弹出节点的值存入栈中,指针指向弹出节点的右子树节点,继续遍历访问弹出节点右子树节点是否为空,重复该步骤直至遍历完该二叉树为止。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> dataList = new ArrayList<Integer>();
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        While(root != null || !stack.isEmpty()){
          If(root!= null){
            stack.push(root);
            root = root.left;
          }else{
            root = stack.pop();
            dataList.add(root.val);
            root = root.right;
         }
       }
       return dataList ;
   }
}

解法二】递归:递归的解法很简单,递归循环左节点和右节点,递归的终止条件是当root为空时返回。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> dataList = new ArrayList<Integer>();
        Inorder(root,dataList );
        return dataList ;
    }
    public void inorder(TreeNode root,List<Integer> dataList){
      If(root == null){
        return;
      }
      inorder(root.left,dataList);
      dataList.add(root.val);
      inorder(root.right,dataList);
    }
}

二叉树的前序遍历

迭代解决】前序遍历的出入栈顺序是:先根节点入栈,根节点出栈,再右节点入栈、左节点入栈,左节点出栈、右节点入栈;如此往复循环直至遍历完整颗二叉树,在每一次出栈时保存节点的值放入list链表,最后得到的list结果集合就是所求结果。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> dataList = new ArrayList<Integer>();
        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        stack.push(root); 
        While( !stack.isEmpty()){
          root = stack.pop();
          dataList.add(root.val);
          //先压入右节点,弹出顺序刚好相反
          If(root.right != null){
            stack.push(root.right );
          }
          //再压入左节点,弹出顺序刚好相反
         If(root.left!= null){
           stack.push(root.left);
         }
       }
     return dataList ;
  }
}

后序遍历】后序遍历的顺序是:左节点-->右节点-->根  而出栈和入栈的顺序则刚好相反,这题的关键是需要用两个栈结构来解答,一个栈用来遍历,另一个栈用来存储,遍历完第一个栈后,第二个栈出栈遍历的结构就是后续遍历。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> dataList = new ArrayList<Integer>();
        //第一个栈用来遍历二叉树
        Deque<TreeNode> stack1 = new LinkedList<TreeNode>();
        stack1.push(root);
        //第二个栈用来存放节点最终遍历出栈的顺序就是所要求结果
        Deque<TreeNode> stack2 = new LinkedList<TreeNode>();
        While(!stack1.isEmpty()){
          root = stack1.pop();
          stack2.push(root.val); 
          If(root.left != null){
            stack1.push(root.left);
          }
          If(root.right != null){
            stack1.push(root.right);
          }
        }
        while(!stack2.isEmpty()){
          dataList.add(stack2.pop());
        }
     }
}

【四】总结

关于二叉树的解法,常见为深度优先遍历和广度优先遍历,深度优先一般选用递归解法,如求二叉树的深度、层序遍历(节点从左到右顺序)、中序遍历、反转二叉树、对称二叉树等,广度优先采用Queue队列、Deque栈的数据结构来求解,一层一层的遍历按照要求实现具体解法,广度优先也称为迭代解法。

我是程序大视界,坚持原创技术博客分享。

注:如果本篇博客有任何纰漏和建议,欢迎私信或评论留言!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序大视界

原创不易,请给点支持和鼓励吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值