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刷穿二叉树的主要内容,如果未能解决你的问题,请参考以下文章