1. 广度优先的实现
  2. 力扣中常见的二叉树相关问题及基本解决方案
    tips: 在解决问题时,先确保问题能解决,再去考虑效率,这是解题的关键,切不可为追求效率而变成了技巧性解答。

广度优先

广度优先(层序遍历)遍历的方式是按层次从上到下,从左到右的逐层访问。

[36, 21, 56, 8, 23, 38,72]

image-20241205134000624

public void levelTraversal(TreeNode root) {
    Deque<TreeNode> queue = new ArrayDeque<>();
    if (root == null) return;
    queue.offer(root);

    while (!queue.isEmpty()) {
        TreeNode peek = queue.pop();
        System.out.println(peek.val);
        if (peek.left != null) {
            queue.offer(peek.left);
        }
        if (peek.right != null) {
            queue.offer(peek.right);
        }
    }
}

力扣问题

  1. 102. 二叉树的层序遍历 - 力扣(LeetCode)
  2. 107. 二叉树的层序遍历 II - 力扣(LeetCode)

二叉树经典例题

计算二叉树的深度

问题

[LCR 175] LCR 175. 计算二叉树的深度 - 力扣(LeetCode)

问题描述

某公司架构以二叉树形式记录,请返回该公司的层级数。

示例 1:

img
输入:root = [1, 2, 2, 3, null, null, 5, 4, null, null, 4]
输出: 4
解释: 上面示例中的二叉树的最大深度是 4,沿着路径 1 -> 2 -> 3 -> 41 -> 2 -> 5 -> 4 到达叶节点的最长路径上有 4 个节点。

解决方案

image-20241204153607653

参考实现

class Solution {
    public int calculateDepth(TreeNode root) {
        if(root == null) return 0;
        return Math.max(calculateDepth(root.left) , calculateDepth(root.right))+1;
    }
}

将有序数组转换为二叉搜索树

问题

108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)

问题描述

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵

平衡二叉搜索树。

示例 1:

img

输入:nums = [-10,-3,0,5,9]
输出:[0,-3,9,-10,null,5]
解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:

示例 2:

img

输入:nums = [1,3]
输出:[3,1]
解释:[1,null,3][3,1] 都是高度平衡二叉搜索树。

解决方案

有序数组拆半放入二叉搜索树。

  • 左边部分放入搜索树左侧
  • 右边部分放入搜索树右侧
image-20241205152303793

参考实现

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        if (nums.length == 0) {
            return null;
        }
        int mid = nums.length / 2;
        TreeNode root = new TreeNode(nums[mid]);
        root.left = sortedArrayToBST(Arrays.copyOfRange(nums, 0, mid));
        root.right = sortedArrayToBST(Arrays.copyOfRange(nums, mid + 1, nums.length));
        return root;
    }
}

寻找二叉搜索树中的目标节点

题目

[LCR174] LCR 174. 寻找二叉搜索树中的目标节点 - 力扣(LeetCode)

题目描述

某公司组织架构以二叉搜索树形式记录,节点值为处于该职位的员工编号。请返回第 cnt 大的员工编号。

示例 1:

img
输入:root = [7, 3, 9, 1, 5], cnt = 2
       7
      / \
     3   9
    / \
   1   5
输出:7

示例 2:

img
输入: root = [10, 5, 15, 2, 7, null, 20, 1, null, 6, 8], cnt = 4
       10
      / \
     5   15
    / \    \
   2   7    20
  /   / \ 
 1   6   8
输出: 8

解决方案

中序解决排序问题

参考实现

class Solution {
    public int findTargetNode(TreeNode root, int cnt) {
        List<Integer> list = new ArrayList<Integer>();
        inOrder(root,list);
      //  System.out.println(list);
        return list.get(list.size()-cnt);
    }

    private void inOrder(TreeNode root,List<Integer> list){
        if(root ==null){
            return ;
        }
        inOrder(root.left,list);
        list.add(root.val);
        inOrder(root.right,list);
    }
}

计算布尔二叉树的值

题目

[力扣2331] 2331. 计算布尔二叉树的值 - 力扣(LeetCode)

题目描述

给你一棵 完整二叉树 的根,这棵树有以下特征:

  • 叶子节点 要么值为 0 要么值为 1 ,其中 0 表示 False1 表示 True
  • 非叶子节点 要么值为 2 要么值为 3 ,其中 2 表示逻辑或 OR3 表示逻辑与 AND

计算 一个节点的值方式如下:

  • 如果节点是个叶子节点,那么节点的 为它本身,即 True 或者 False
  • 否则,计算 两个孩子的节点值,然后将该节点的运算符对两个孩子值进行 运算

返回根节点 root 的布尔运算值。

完整二叉树 是每个节点有 0 个或者 2 个孩子的二叉树。

叶子节点 是没有孩子的节点。

示例 1:

img
输入:root = [2,1,3,null,null,0,1]
输出:true
解释:上图展示了计算过程。
AND 与运算节点的值为 False AND True = FalseOR 运算节点的值为 True OR False = True 。
根节点的值为 True ,所以我们返回 true

示例 2:

输入:root = [0]
输出:false
解释:根节点是叶子节点,且值为 false,所以我们返回 false

解决方案

递归根据情况进行分类。

image-20241204164220106

参考实现

class Solution {
    public boolean evaluateTree(TreeNode root) {
        if(root.val ==1) return true;
        else if(root.val == 0) return false;
        else if(root.val ==2) return evaluateTree(root.left) || evaluateTree(root.right);
        else  return evaluateTree(root.left) && evaluateTree(root.right);
    }
}

二叉搜索树的范围和

问题

[力扣938] 938. 二叉搜索树的范围和 - 力扣(LeetCode)

问题描述

给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和。

示例 1:

img

输入:root = [10,5,15,3,7,null,18], low = 7, high = 15
输出:32

示例 2:

img

输入:root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10
输出:23

解决方案

从根节点递归到叶节点的过程中,如果小于low,则走右侧(值的范围必须大于等于low)

如果大于high,则走左侧(值的范围必须小于等于high),

如果在范围内[low, high], 则继续遍历其子节点。

参考实现

放入List集合中,按照集合中数据的访问遍历。

class Solution {
    public int rangeSumBST(TreeNode root, int low, int high) {
        List<Integer>  list  = new ArrayList<>();
        inOrder(root, list);
        int sum=0;
        for(int t :  list){
            if(t >=low && t <=high){
                sum+=t;
            }
        }
        return sum;
    }

    private void inOrder(TreeNode root, List<Integer> list){
        if(root == null) return ;
        inOrder(root.left, list);
        list.add(root.val);
        inOrder(root.right, list);
    }

}

当前递归节点与low和high进行比较

  • root< low : 说明左侧没有合适的值,那么继续递归右侧
  • root > right: 说明右侧没有合适的值,那么继续递归左侧
  • root 在范围之内,则将左侧和右侧的结果相加+ 当前节点的值。
class Solution {
    public int rangeSumBST(TreeNode root, int low, int high) {
        if(root == null) return 0;
        if(root.val < low){
            return rangeSumBST(root.right, low, high);
        }
        if(root.val > high){
            return rangeSumBST(root.left, low, high);
        }

        return rangeSumBST(root.left,low,high)
               + rangeSumBST(root.right,low,high)
               + root.val;
    }
}

二叉搜索树中第K小的元素

题目

230. 二叉搜索树中第 K 小的元素 - 力扣(LeetCode)

题目描述

给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 小的元素(从 1 开始计数)。

示例 1:

img

输入:root = [3,1,4,null,2], k = 1
输出:1

示例 2:

img

输入:root = [5,3,6,2,4,null,null,1], k = 3
输出:3

解决方案

中序遍历存入list集合

找到list中的第k小项

参考实现

class Solution {
    public int kthSmallest(TreeNode root, int k) {
     List<Integer> list = new ArrayList<>();   
     inOrder(root,list);
    return list.get(k-1);
    }

    private void inOrder(TreeNode root,List<Integer> list){
        if(root==null) return ;
        inOrder(root.left, list);
        list.add(root.val);
        inOrder(root.right,list);
    }
}

二叉搜索树中的中序后继

题目

[力扣LCR053] LCR 053. 二叉搜索树中的中序后继 - 力扣(LeetCode)

题目分析

给定一棵二叉搜索树和其中的一个节点 p ,找到该节点在树中的中序后继。如果节点没有中序后继,请返回 null

节点 p 的后继是值比 p.val 大的节点中键值最小的节点,即按中序遍历的顺序节点 p 的下一个节点。

示例 1:

img

输入:root = [2,1,3], p = 1
输出:2
解释:这里 1 的中序后继是 2。请注意 p 和返回值都应是 TreeNode 类型。

示例 2:

img

输入:root = [5,3,6,2,4,null,null,1], p = 6
输出:null
解释:因为给出的节点没有中序后继,所以答案就返回 null 了。

解决方案

  1. 中序记录在List集合中,找到p在list中的位置索引,如果索引>=0 || 不是最后一个位置则返回,否则返回null。
  2. 记录上一个节点pre, 当前curr。

参考实现

class Solution {
    public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
        Stack<TreeNode> stack = new Stack<>();

        TreeNode curr = root;
        TreeNode pre = null;

        while(curr!=null || !stack.isEmpty()){
            while(curr!=null){
                stack.push(curr);
                curr = curr.left;
            }
           curr = stack.pop();
           if(pre == p){
             return   curr;
           }
           pre = curr;
           curr = curr.right;
        }
        return null;
    }
}

两数之和IV-输入二叉搜索树

问题

[力扣653] 653. 两数之和 IV - 输入二叉搜索树 - 力扣(LeetCode)

问题描述

给定一个二叉搜索树 root 和一个目标结果 k,如果二叉搜索树中存在两个元素且它们的和等于给定的目标结果,则返回 true

示例 1:

img

输入: root = [5,3,6,2,4,null,7], k = 9
输出: true

示例 2:

img

输入: root = [5,3,6,2,4,null,7], k = 28
输出: false

解决方案

  1. 将数据存入一个List集合
  2. 问题转换为找到一个集合中的和为K的两个数。

参考实现

class Solution {
    public boolean findTarget(TreeNode root, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        List<Integer> list = new ArrayList<>();
        final int DEFAULT_VAL = 999;
        inOrder(root, list);

        //System.out.println(list);

        for(int t : list){
            int target = k - t;
            if(map.containsKey(target)){
                return true;
            }
            map.put(t, DEFAULT_VAL);
        }

        return false;
    }

    private void inOrder(TreeNode root, List<Integer> list) {
        if (root == null) return ;
        inOrder(root.left, list);
        list.add(root.val);
        inOrder(root.right, list);
    }
}
class Solution {
    public boolean findTarget(TreeNode root, int k) {
        Map<Integer,Integer> map = new HashMap<>();
        List<TreeNode> stack  = new ArrayList<>();
        TreeNode curr = root;

        while(curr!=null || !stack.isEmpty()){
            while(curr!=null){
                int target= k - curr.val;
                if(map.containsKey(target)){
                    return true;
                }
                map.put(curr.val,999);
                stack.add(curr);
                curr = curr.left;
            }
            curr = stack.remove(stack.size()-1);
            curr = curr.right;
        }
        return false;
    }
}
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐