剑指Offer 54-55 、二叉树(二叉搜索树、平衡二叉树)

149 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

题目:第54题,要求找出二叉搜索树的第k大的节点。

第55题对应两个子问题,第一个问题是求一颗二叉树的深度,第二个是判断一棵树是否是平衡二叉树。

解题思路

首先来看第54题,根据二叉搜索树的特性,本题的解决很简单。我们需要注意一个重要的知识点,一颗二叉搜索树的中序遍历即为有序序列。本题要求找出第k大的节点,那么我们通过右子树-根节点-左子树的方式遍历整棵树就可以得到序列的逆序。当遍历到第k个节点的时候就可以截断,可得代码如下:

private int cur = 0;
private int value = 0;

public int kthLargest(TreeNode root, int k) {
    search(root, k);
    return value;
}

public void search(TreeNode root, int k){
    if(root == null) return ;
    search(root.right, k);
    cur ++ ;
    if(cur == k){
        value = root.val;
        return;
    }
    search(root.left, k);
}

之后来看第55题的第一问,求二叉树的深度,可以通过层序遍历的方式来得到树的深度,每当一层中的元素遍历完成即深度加1,简单的实现方式是使用队列来记录节点,按照先左子树后右子树的方式将节点入队,之后依次弹出即可,此外还需要使用一个额外的变量来记录本层的节点是否已经遍历完,根据当前队列的元素数量来更新每层的节点数量,可得代码如下:

public int maxDepth(TreeNode root) {
    if(root==null) return 0;
    int maxDepth = 0;
    ArrayDeque<TreeNode> deque = new ArrayDeque<>();
    deque.offer(root);
    int cur = 1;
    while(!deque.isEmpty()){
        TreeNode poll = deque.poll();
        cur --;
        if(poll.left!=null) deque.offer(poll.left);
        if(poll.right!=null) deque.offer(poll.right);
        if(cur == 0){
            cur = deque.size();
            maxDepth ++;
        }
    }
    return maxDepth;
}

另一种方式是使用递归,通过比较左右子树的深度来得到整棵树的深度,可得代码如下:

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

第二问是判断一棵树是否是平衡二叉树,平衡二叉树要求左子树右子树的深度不能大于1,并且所有的子树都需要满足这一条件,实际上通过这个性质就很容易可以得到本题的答案,可得代码如下:

public boolean isBalanced(TreeNode root) {
    if(root == null) return true;
    if(Math.abs(maxDepth(root.left)-maxDepth(root.right))<=1){
        return isBalanced(root.left) && isBalanced(root.right);
    }
    return false;
}

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