「刷题」2.二叉树的题刷不动?快进来拓展解题思路!

本文介绍了如何通过层序遍历实现二叉树的右视图问题,以及使用两种方法找到二叉树中最近公共祖先节点,最后讲解了如何根据二叉树结构构建字符串,涉及知识点包括递归和栈的应用。
摘要由CSDN通过智能技术生成

🎇个人主页Ice_Sugar_7
🎇所属专栏数据结构刷题
🎇欢迎点赞收藏加关注哦!

🍉二叉树右视图

题目链接

思路:采用层序遍历的思路,遍历每一层的时候,先创建一个数组存放该层节点,遍历完一层后,取出最右边的节点(即数组最后一个元素),将它们的val都存进顺序表ret,返回即可

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        if(root == null)
            return new ArrayList<>();
        //层序遍历,一层一个数组,每层取该层数组最后一个元素
        List<Integer> list = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            List<Integer> list1 = new ArrayList<>();
            int size = queue.size();
            while(size-- > 0) {
                TreeNode pop = queue.poll();
                if(pop.left != null) {
                    queue.offer(pop.left);
                }
                if(pop.right != null) {
                    queue.offer(pop.right);
                }
                list1.add(pop.val);
            }
            int last = list1.get(list1.size()-1);  //得到该层最右的节点的val
            list.add(last);
        }
        return list;
    }
}

涉及到的知识点:

  • 层序遍历

🍉二叉树的最近公共祖先

题目链接

思路:公共祖先节点有两种情况

  1. q和p分居祖先节点的左、右子树
  2. q和p都在祖先节点的左子树或右子树

第一种情况:此时root就是祖先节点
第二种情况:祖先节点就是q或p,在遍历的过程中,先遍历到谁,谁就是祖先节点(假设q是祖先节点,那这种情况下,p一定在q的子树之中)

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null)
            return null;
        if(root == p)
            return p;
        if(root == q)
            return q;

        //遍历左、右子树找q、p
        TreeNode ret1 = lowestCommonAncestor(root.left,p,q);
        TreeNode ret2 = lowestCommonAncestor(root.right,p,q);

		//如果ret1和ret2都不为空,就是第一种情况
		//若有一个为空,则是第二种
		//有的节点向左右子树找是找不到的,此时要返回null
        if(ret1 != null && ret2 != null) {
            return root;
        } else if(ret1 == null && ret2 != null) {
            return ret2;
        } else if(ret1 != null && ret2 == null) {
            return ret1;
        } else {
            return null;
        }
    }
}

以上是第一种解法,接下来说另一种
我们可以参考相交链表找相交点的思路。之前是单链表,现在是二叉树,区别在于二叉树没办法存储遍历过的节点

  1. 所以我们要用两个辅助栈来存储节点
  2. 将节点都入栈之后,节点比较多的栈要先出栈,直到两个栈的size相同
  3. 接下来两个栈同时出栈,比较栈顶元素pop1和pop2,当pop1 == pop2时,说明这个节点就是相交节点
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        TreeNode cur = root;
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();

        getPath(cur,q,stack1);
        getPath(cur,p,stack2);

        int sizeQ = stack1.size();
        int sizeP = stack2.size();
        if(sizeQ > sizeP) {
            int size = sizeQ - sizeP;
            while(size-- > 0) {
                stack1.pop();
            }
        }
        if(sizeQ < sizeP) {
            int size = sizeP - sizeQ;
            while(size-- > 0) {
                stack2.pop();
            }
        }

        while(!stack1.isEmpty()) {
            TreeNode pop1 = stack1.pop();
            TreeNode pop2 = stack2.pop();
            if(pop1.val == pop2.val) {
                return pop1;
            }
        }
        return root;

    }

    private boolean getPath(TreeNode root,TreeNode node,Stack<TreeNode> stack) {
        if(root == null)
            return false;
        //一定要在比较root和node的val之前入栈,否则可能会导致路径上最后一个节点没入栈
        stack.push(root);
        if(root.val == node.val)
            return true;
        boolean ret1 = getPath(root.left,node,stack);
        if(!ret1) {
            //左边找不到就去找右边
            boolean ret2 = getPath(root.right,node,stack);
            if(!ret2) { //右边还是找不到的话,说明这条路径上没有我们要找的节点,那就把这个节点出栈
                stack.pop();
                return false;
            }
        }
        return true;
    }
}

🍉根据二叉树创建字符串

题目链接

思路:对每个根节点进行分类讨论,分析如何添加括号

  1. 左右子树为空,即叶子节点,这个就不用处理
  2. 左子树为空,右子树不为空,得加完整的括号
  3. 左子树不为空,右子树为空,也不用添加括号

每次递归之前,都先加上左括号,递归出来后,加上右括号
如果某棵子树为空,那我们就不用再往这棵子树递归下去了

class Solution {
    StringBuilder ret = new StringBuilder();

    public String tree2str(TreeNode root) {
        if(root == null)
            return new String();
        ret.append(root.val);

        //对根节点进行分析
        //1.左右都空:不处理
        //2.左空右不空:补整个括号
        //3.左不空右空:不处理
        if(root.left != null) {
            ret.append('(');
            //处理左树
            tree2str(root.left);
            ret.append(')');  //处理完补右括号
        } else {
            if(root.right != null) {
                ret.append("()");
            }
        }        
        //处理右树
        if(root.right != null) {
            ret.append('(');
            tree2str(root.right);
            ret.append(')');
        }
        return ret.toString();
    }
}
  • 30
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值