• 二叉树/n叉树的解题思路


    二叉树

    • 二叉树特点是每个节点最多只能有两棵子树,且有左右之分
    • 二叉树的数据结构如下:
    public class TreeNode {
       //节点的值
       int val;
       //左子树
       TreeNode left;
       //右子树
       TreeNode right;
       TreeNode(int x) { val = x; }
    }
    
    • 树节点的初始化:
        int val=1;
        TreeNode node = new TreeNode(val);
    
    • 获取树的节点node的值:
       int val = node.val;
    
    • 二叉树的节点为node,求左右子树:
       TreeNode right =node.right;
       TreeNode left= node.left;
    
    • N叉树的节点结构如下:
    class Node {
        public int val;
        public List<Node> children;
    }
    

    树的遍历

    树的遍历方式有:前序遍历(又叫先序遍历)、中序遍历、后序遍历
    前序遍历:根节点,左节点,右节点。
    中序遍历:左节点,根节点,右节点。
    后序遍历:左节点,右节点,根节点。

    递归法

    树经常会用到递归。

    比如二叉树的中序遍历(LeetCode94)。
    先序遍历、后序遍历也类似,只是调换了节点的顺序而已。

    public class LeetCode94 {
        //list设置为成员变量,如果是方法内变量,无法一直添加元素
        private List<Integer> list = new ArrayList<>();
    
        public List<Integer> inorderTraversal(TreeNode root) {
            if (root == null) {
                return list;
            }
            //中序遍历:左节点,根节点,右节点。
            inorderTraversal(root.left);
            list.add(root.val);
            inorderTraversal(root.right);
            
            return list;
        }
    }
    

    比如N叉树的前序遍历(LeetCode589)。

    class LeetCode589{
        //list设置为成员变量,如果是方法内变量,无法一直添加元素
        private List<Integer> list = new LinkedList<>();
    
        public List<Integer> preorder(Node root) {
    	if(root==null) {
                return list;
            }
            list.add(root.val);
            for (Node node : root.children) {
                preorder(node);
            }
    	return list;
        }
    }
    

    迭代法

    • 树还可以用迭代法。利用栈的先进后出解题。
      迭代法是DFS和BFS的基础,可以多学习一下。

    N叉树的前序遍历。

    class Solution {
        public List<Integer> preorder(Node root) {
            List<Integer> list = new ArrayList<>();
            if (root == null) return list;
            //将根节点数据添加到栈中
            Stack<Node> stack = new Stack<>();
            stack.add(root);
            
            while (!stack.empty()) {
                //栈顶的数据,出栈
                root = stack.pop();
                //在list中添加栈顶数据
                list.add(root.val);
                //将子节点全部放入栈里面,由于栈是后进先出,所以后面的子节点先放入
                for (int i = root.children.size() - 1; i >= 0; i--)
                    stack.add(root.children.get(i));
            }
            
            return list;
        }
    }
    
    

    BFS(广度优先搜索算法)。

    BFS的操作步骤如下:
    1、使用 Queue的 offer()方法把树的根节点放入 Queue;
    2、重复以下步骤,直到 Queue为空为止(也就是while循环条件为 !queue.isEmpty()):
    (1)获取 Queue的size, 因为Queue中存放的其实就是每一层中所有的节点, size就相当于每一层的数量,也就是宽度
    (2)遍历队列,直到当前这一层所有的节点都遍历完(也就是while循环条件为 size-- > 0 )
    (3)在遍历过程中,使用 Queue的 offer()方法得到队列中的节点,根据节点查出它的左节点和右节点,并用offer()方法放入队列中。

    题目:LeetCode104、LeetCode102

    示例:求二叉树的最大深度。

    public class LeetCode104BFS {
    	public int maxDepth(TreeNode root) {
    		if (root == null){
                          return 0;
    		}
    		int depth = 0;
    		Queue<TreeNode> queue= new LinkedList<>();
    		//队列使用offer和poll不会抛异常
                    //首先,要将根节点放入队列中。
    		nodes.offer(root);
    		while (!queue.isEmpty()) {
                            //队列中存放的其实就是每一层中所有的节点
                            //size就相当于每一层的数量,也就是宽度
    			int size = queue.size();
    			//遍历一次,深度就加一
    			depth++;
    			//遍历队列中的数据,直到当前这一层所有的节点都遍历完
    			while (size-- > 0) {
                                //取出队列中的树节点
                                TreeNode node = queue.poll();
                                //将当前节点的左右子树,放入队列中。
                                if (node!=null && node.left != null){
                                      queue.offer(node.left);
                                }
                                if (node!=null && node.right != null){
                                      queue.offer(node.right);
                                }
    			}
    		}
    		return depth;
    	}
    }
    

    DFS(深度优先搜索算法)

    以深度优先为策略,从根节点开始一直遍历到某个叶子节点。

    DFS的实现方式相比于BFS应该说大同小异,只是把 queue 换成了stack而已,stack具有后进先出LIFO(Last Input First Output)的特性,DFS的操作步骤如下:
    1、把起始点放入stack;
    2、重复下述3步骤,直到stack为空为止:
    (1)从stack中访问栈顶的点;
    (2)找出与此点邻接的且尚未遍历的点(也就是子节点),进行标记,然后全部放入stack中;
    (3)如果此点没有尚未遍历的邻接点,则将此点从stack中弹出。

    参考资料

    leetCode

  • 相关阅读:
    springboot 踩坑之表单验证
    爬虫学习研究
    selenium+chrome知识
    每天学一点linux命令
    Javascript禁止子元素继承父元素的事件
    sass编译css(转自阮一峰)
    php配置虚拟主机的配置步骤(hosts、httpd.conf、vhosts.conf)1.配置本地的dns文件2.配置apache的主配置文件3.配置Apache的虚拟主机
    修改原代码定制bootstrap
    网页在线进行标准验证
    浏览器兼容性判定写法格式(ie)
  • 原文地址:https://www.cnblogs.com/expiator/p/16069108.html
Copyright © 2020-2023  润新知