leetcode刷穿二叉树

Posted 深林无鹿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode刷穿二叉树相关的知识,希望对你有一定的参考价值。

拿下二叉树的第五天

在这里插入图片描述
专辑完结,欢迎查看本系列文章:
leetcode刷穿二叉树(一)
leetcode刷穿二叉树(二)
leetcode刷穿二叉树(三)
leetcode刷穿二叉树(四)
leetcode刷穿二叉树(五)
leetcode刷穿二叉树(六)
建议收藏~

这里有leetcode题集分类整理!!!

  • leetcode 501. 二叉搜索树中的众数
  • leetcode 236. 二叉树的最近公共祖先
  • leetcode 35. 二叉搜索树的最近公共祖先
  • leetcode 701. 二叉搜索树中的插入操作
  • leetcode 450. 删除二叉搜索树中的节点

1、二叉搜索树中的众数
题目难度:简单
题目描述:
在这里插入图片描述
解题思路:

根据题意,我们得知,必须要遍历完所有节点才能知道答案,并且属于统计类对问题,因此采取什么遍历方式都可以达到目的,这里我们利用BST中序遍历的有序性,可以省去一个哈希表来存取元素的数量。
采用变量如下:

  • count 变量来统计当前元素个数;
  • maxCount 统计当前众数的元素对应的个数;
  • base 记录上次遍历到的数字(以拿来后续的判断)

采用方法如下:

  • inOrderTraversal(TreeNode node) 中序遍历BST
  • update(int x) 用于每次遍历时判断当前节点对值是否属于众数
class Solution {
    private List<Integer> res = new ArrayList<>();
    private int base, count, maxCount;
    public int[] findMode(TreeNode root) {
        inOrderTraversal(root);
        int len = res.size();
        int[] ans = new int[len];
        for (int i = 0; i < len; i ++) {
            ans[i] = res.get(i);
        }
        return ans;
    }

    public void inOrderTraversal(TreeNode node) {
        if (node == null) return;
        inOrderTraversal(node.left);
        update(node.val);
        inOrderTraversal(node.right);
    }

    public void update(int x) {
        if (x == base) {
            count ++;
        } else {
            base = x;
            count = 1;
        }
        if (count == maxCount) {
            res.add(x);
        }
        if (count > maxCount) {
            maxCount = count;
            res.clear();
            res.add(x);
        }
    }
}

2、二叉树的最近公共祖先
题目难度:中等
题目描述:
在这里插入图片描述
在这里插入图片描述
解题思路一:

求公共祖先类问题,需要自底向上遍历树,而自底向上就可以采用后序遍历的性质来实现。
递归的终止条件:

  • 叶子节点不是p、q,返回null
  • 节点是p或q, 返回这个节点

后序遍历的处理逻辑:

  • 同时不为空,说明是p、q为该节点的左右孩子辈,返回该节点
  • 一个为空,说明找到其中一个节点,或找到了公共祖先,返回不为空的节点。
  • 都为空,则没有找到左右节点或公共祖先,返回null

需要注意的一点:自底向上搜索的时候需要遍历整棵树,无法提前返回

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || root.val == p.val ||root.val == q.val) return root;
        TreeNode left = lowestCommonAncestor(root.left,p,q);
        TreeNode right = lowestCommonAncestor(root.right,p,q);
        if (left != null && right != null) return root;
        else if (left == null && right != null) return right;
        else if (left != null && right == null) return left;
        else return null;
    }
}

解题思路二:

采用将父节点存入哈希表的方式
执行方法:

  • 在dfs的过程中将节点的值,对应的父节点存入哈希表(parent)中,用来后续求得某个节点的祖先节点集合(visited中)。
  • 遍历某个目标节点(p或q),将它的祖先节点们加入visited集合之中。
  • 遍历另一个目标节点,从哈希表中不断的向上获取父亲节点,直到在visited集合中找到这个父节点,那么这个父节点就是最小公共祖先了。
class Solution {
    HashMap<Integer, TreeNode> parent = new HashMap<>();
    Set<Integer> visited = new HashSet<>();

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        dfs(root);
        while (p != null) {
            visited.add(p.val);
            p = parent.get(p.val);
        }

        while (q != null) {
            if (visited.contains(q.val)) {
                return q;
            }
            q = parent.get(q.val);
        }
        return null;
    }

    public void dfs(TreeNode node) {
        if (node.left != null) {
            parent.put(node.left.val, node);
            dfs(node.left);
        }
        if (node.right != null) {
            parent.put(node.right.val, node);
            dfs(node.right);
        }
    }
}

3、 二叉搜索树的最近公共祖先
题目难度:简单
题目描述:
在这里插入图片描述
解题思路:

这道题比第二题简单的一点就是在BST中寻找公共祖先。
可以利用BST查找遍历的特性:左小右大 来很方便的去获得我们想要的信息
在这道题中: 找公共祖先之需要满足
lca < [p, q] 就向右查找
[p,q] < lca 就向左查找
直到 p < lca (lowest common ancestor) < q 即可返回

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root.val > p.val && root.val > q.val) {
            return lowestCommonAncestor(root.left, p, q);
        } else if (root.val < p.val && root.val < q.val) {
            return lowestCommonAncestor(root.right, p, q);
        } else return root;
    }
}

4、二叉搜索树中的插入操作
题目难度:中等
题目描述:
在这里插入图片描述
解题思路:

插入一个新的值二叉搜索树:

  • 递归遍历BST:
    • 如果目标数值比当前节点小,向左遍历
    • 如果目标数值比当前节点大,向右遍历
    • 一直递归到空节点,即为待插入的位置
  • 找到插入的位置后新建节点,返回
class Solution {
    public TreeNode insertIntoBST(TreeNode root, int val) {
        if (root == null) {
            TreeNode node = new TreeNode(val);
            return node;
        }
        if (root.val > val) root.left = insertIntoBST(root.left, val);
        if (root.val < val) root.right = insertIntoBST(root.right, val);
        return root;
    }
}

5、删除二叉搜索树中的节点
题目难度:中等
题目描述:
在这里插入图片描述
解题思路:

删除搜索二叉搜索树的节点
首先确定递归的终止条件:
有以下几种情况:

  • 节点为空 -> 没有搜索到目标节点,返回空
  • 找到节点,节点没有左右孩子 -> 直接将节点置空。
  • 找到节点,节点只有左孩子 -> 返回左孩子
  • 找到节点,节点只有右孩子 -> 返回右孩子
  • 找到节点,有两个孩子的时候,我们有两种可选择对方案:(结果性质一样)
    • 将左孩子插入到右孩子的最左端,将右孩子返回
    • 将右孩子插入到左孩子的最右端,将左孩子返回
class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if (root == null) return null;
        if (root.val == key && root.left == null && root.right == null) {
            return null;
        }
        if (root.val == key && root.left != null && root.right == null) {
            return root.left;
        }
        if (root.val == key && root.left == null && root.right != null) {
            return root.right;
        }
        if (root.val == key && root.left != null && root.right != null) {
            TreeNode l = root.left;
            TreeNode pl = root;
            while (l != null) {
                pl = l;
                l = l.right;
            }
            pl.right = root.right;
            return root.left;
        }
        root.left = deleteNode(root.left, key);
        root.right = deleteNode(root.right, key);
        return root;
    }
}

专辑完结,欢迎查看本系列文章:
leetcode刷穿二叉树(一)
leetcode刷穿二叉树(二)
leetcode刷穿二叉树(三)
leetcode刷穿二叉树(四)
leetcode刷穿二叉树(五)
leetcode刷穿二叉树(六)
原创不易,三连支持一下喔~
在这里插入图片描述

以上是关于leetcode刷穿二叉树的主要内容,如果未能解决你的问题,请参考以下文章

leetcode刷穿二叉树

leetcode刷穿二叉树

leetcode刷穿二叉树

leetcode刷穿二叉树(完结)

leetcode刷穿二叉树(完结)

leetcode刷穿二叉树(完结)