前言

又是学习LeetCode二叉树的新一天,今天还是接着学习一下二叉搜索树的内容,希望博主记录的内容能够对大家有所帮助 ,一起加油吧朋友们!💪💪💪

二叉搜索树中的众数

LeetCode题目链接

给一个含重复值的二叉搜索树的根节点root,返回该树的所有众数(以数组格式)

1727703878511

思路梳理:这道题其实也是可以利用二叉搜素数中序遍历节点值递增的规律来写,因为就是可以在递归遍历的时候去更新当前节点频率和最大节点频率来完成这样,当当前节点频率大于等于最大节点频率时就把当前节点的值加入到一个整数列表中🤔🤔🤔

我们接下来梳理递归三要素

1
2
// 定义了结果的列表所以无需返回值,然后前序节点值和当前频率、最大频率用变量保存故参数只有数的根节点即可
private void inOrderTraversal(TreeNode root){}
1
2
//因为要处理每个节点所以会进入空节点
if(root == null) return;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//递归单层处理逻辑
inOrderTraversal(root.left);// 递归遍历左子树

if(root.val == preVal){ // 处理当前节点
curCount++;
}else{
curCount = 1;
}

if(curCount > maxCount){ // 判断是否需要更新众数列表
maxCount = curCount;
result.clear();
result.add(root.val);
}
else if(curCount == maxCount){// 如果当前频率等于最大频率也加入到众数列表中
result.add(root.val);
}
preVal = root.val;// 更新前一个节点的值为当前值


inOrderTraversal(root.right);// 递归遍历右子树

完整代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**递归法 */
class Solution {
private int maxCount = 0; //最大频率
private int curCount = 0;//当前频率
private int preVal = Integer.MIN_VALUE;//记录前一个节点的值
private List<Integer> result = new ArrayList<>();//记录众数结果
public int[] findMode(TreeNode root) {
inOrderTraversal(root);
return result.stream().mapToInt(Integer::intValue).toArray();
}

private void inOrderTraversal(TreeNode root){ //中序遍历
//递归出口
if(root == null) return;

//递归单层处理逻辑
inOrderTraversal(root.left);

if(root.val == preVal){ //更新频率
curCount++;
}else{
curCount = 1;
}

if(curCount > maxCount){ //更新众数
maxCount = curCount;
result.clear();
result.add(root.val);
}
else if(curCount == maxCount){
result.add(root.val);
}
preVal = root.val;//更新存储的前节点的值


inOrderTraversal(root.right);

}
}

这里可以提一下的是最后将列表转换成整型数组的一步操作

1
return result.stream().mapToInt(Integer::intValue).toArray();
1
2
3
4
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream() // 生成流
.filter(name -> name.startsWith("A")) // 过滤出以"A"开头的名字
.forEach(System.out::println); // 输出满足条件的名字
1
2
3
4
5
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int[] result = numbers.stream()
.mapToInt(Integer::intValue) // 将 Integer 转换为 int
.toArray(); // 转换为 int[]
// result 是 [1, 2, 3, 4]
1
2
3
result.stream().mapToInt(Integer::intValue).toArray();
result.stream().mapToDouble(Double::doubleValue).toArray();
result.stream().mapToLong(Long::longValue).toArray();

我们也来梳理一下迭代法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**迭代法 */
class Solution {
public int[] findMode(TreeNode root) {
int maxCount = 0; //最大频率
int curCount = 0;//当前频率
int preVal = Integer.MIN_VALUE;//记录前一个节点的值
List<Integer> result = new ArrayList<>();//记录众数结果
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(cur != null || !stack.isEmpty()){
if(cur != null){ //中序遍历得先把中和左给压栈
stack.push(cur);
cur = cur.left;
}else{
cur = stack.pop(); //弹出中节点
if(cur.val == preVal){
curCount++;
}else{
curCount = 1;
}

if(curCount > maxCount){
maxCount = curCount;
result.clear();
result.add(cur.val);
}else if(curCount == maxCount){
result.add(cur.val);
}
preVal = cur.val;
cur = cur.right;//处理右节点
}
}
return result.stream().mapToInt(Integer::intValue).toArray();
}


}

二叉树的最近公共祖先

LeetCode题目链接

给定一个二叉树,找到该树中两个指定节点的最近公共祖先

1728300621147

我们来进行思路梳理🤔🤔🤔

1
2
3
4
5
6
递归函数返回值 递归函数(递归参数给定节点p,递归参数给定节点q,递归参数二叉树根节点root){
//递归出口
//处理左子树
//处理右子树
//处理中间父结点
}

1728301538366

1
2
3
4
5
6
TreeNode 递归函数(递归参数给定节点p,递归参数给定节点q,递归参数二叉树根节点root){
if(root == q || root == p || root == null) return root;//递归出口
//处理左子树
//处理右子树
//处理中间父结点
}

思路梳理完毕后我们来紧接着梳理递归三要素🤔🤔🤔

1
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {}
1
if(root == q || root == p || root == null) return root;
1
2
3
4
5
6
/**单层处理逻辑 */
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);//后序遍历
if(left != null && right != null) return root;
if(left == null) return right;
return left;

递归法java代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
/**递归法 */
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == q || root == p || root == null) return root;

/**单层处理逻辑 */
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);//后序遍历
if(left != null && right != null) return root;
if(left == null) return right;
return left;
}
}

我们接着来梳理迭代法的思路🤔🤔🤔

1
HashMap<TreeNode,TreeNode> parentMap = new HashMap<>();//哈希表存储每个节点的父节点
1
2
3
4
5
6
7
8
9
10
11
HashSet<TreeNode> ancestors = new HashSet<>();//准备处理p/q节点的全部父节点路径
while(p != null){ //列出p的所有祖先节点
ancestors.add(p);
p = parentMap.get(p);
}

while(!ancestors.contains(q)){//查找p的所有祖先节点中的第一个公共祖先
q = parentMap.get(q);
}

return q;

完整迭代法代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**迭代法 */
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return null;//提前结束
HashMap<TreeNode,TreeNode> parentMap = new HashMap<>();//哈希表存储每个节点的父节点
Stack<TreeNode> stack = new Stack<>();
stack.push(root);//准备前序遍历
parentMap.put(root, null); //根节点没有父结点

while(!parentMap.containsKey(q) || !parentMap.containsKey(p)){ //直到路径找到p和q
TreeNode cur = stack.pop();

if(cur.left != null){//处理左子树
parentMap.put(cur.left, cur);
stack.push(cur.left);
}

if(cur.right != null){//处理右子树
parentMap.put(cur.right, cur);
stack.push(cur.right);
}
}

HashSet<TreeNode> ancestors = new HashSet<>();//准备处理p/q节点的全部父节点路径
while(p != null){ //列出p的所有祖先节点
ancestors.add(p);
p = parentMap.get(p);
}

while(!ancestors.contains(q)){//查找p的所有祖先节点中的第一个公共祖先
q = parentMap.get(q);
}

return q;
}

二叉搜索树的最近公共祖先

LeetCode题目链接

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先

1728305460702

我们来进行思路梳理🤔🤔🤔

ok,我们直接梳理递归三要素

1
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {}
1
if(root == null) return root;
1
2
3
4
5
6
7
if(root.val > q.val && root.val > p.val){
return lowestCommonAncestor(root.left, p, q);//往左找
} else if(root.val < q.val && root.val < p.val){
return lowestCommonAncestor(root.right, p, q);//往左找
}else{
return root;//找到了
}

总的递归代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
/**递归法 */
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return root;
if(root.val > q.val && root.val > p.val){
return lowestCommonAncestor(root.left, p, q);//往左找
} else if(root.val < q.val && root.val < p.val){
return lowestCommonAncestor(root.right, p, q);//往左找
}else{
return root;//找到了
}
}
}

我们接着来梳理迭代法的逻辑🤔🤔🤔

迭代法代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**迭代法 */
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(root != null){
if(root.val > q.val && root.val > p.val) {
root = root.left;
}else if(root.val < q.val && root.val < p.val){
root = root.right;
}else{
return root;
}
}
return null;
}
}

总结

国庆假期结束,开始加油啦✊✊✊