leetcode - 二叉搜索树相关

1. 剑指 Offer 54. 二叉搜索树的第k大节点

难度 ⭐

🌈 题目描述
给定一棵二叉搜索树,请找出其中第k大的节点。

📢 示例

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

分析:
二叉搜索树的一个性质就是,如果按照中序遍历之,一定是从小到大排序的。所以,可以利用这个性质来求第k大。

class Solution {
public:
    int kthLargest(TreeNode* root, int k) {
        vector<int> arr;
        traverse_mid(root,arr);//arr传引用,得到从小到大排序的数组
        int len = arr.size();
        return arr[len-k];//第k大
    }
    void traverse_mid(TreeNode* root, vector<int> &arr){//中序遍历
        if(root == NULL)
            return;
        traverse_mid(root->left,arr);//访问左边
        arr.push_back(root->val);//访问自己
        traverse_mid(root->right,arr);//访问右边
    }
};

注:在递归中,如果已经考虑了root == NULL的情况,剩下的情况都是平凡的了,只需考虑任意一种节点,不用区分叶节点/非叶节点。
在这里插入图片描述

2. 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

难度 ⭐

🍵 题目描述

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

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]

在这里插入图片描述

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 输出: 6 解释: 节点 2
和节点 8 的最近公共祖先是 6。

🎨 思路

虽然这是一道简单题,但是乍一看我还真没有思路…不过知道思路了之后就会发现其实很简单!
首先,从根节点开始,找到节点p和节点q,并把到p和q的路径记录下来,分别记作path_p和path_q.
例如,从6->2的路径为path_p = [6,2]; 从6->4的路径为path_q = [6,2,4]. 取二者第一次不一样的地方,就可以找到最近公共祖先了。

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        vector<TreeNode*> path1 = find(root,p);
        vector<TreeNode*> path2 = find(root,q);
        int len = min(path1.size(),path2.size());
        for(int i = 0;i<len;i++){
            if(path1[i]->val!=path2[i]->val)
                return path1[i-1]; //find!
        }
        //all the same
        return path1[len-1];

    }
    vector<TreeNode*> find(TreeNode* root, TreeNode* target){ //record the path from root to target
        vector<TreeNode*> ans;
        TreeNode* tmp = root;
        while(1){
            ans.push_back(tmp);
            if(tmp->val == target->val)
                break;
            if(target->val > tmp->val)
                tmp = tmp->right;
            else
                tmp = tmp->left;
        }
        return ans;
    }

};

在这里插入图片描述

3. 剑指 Offer 33. 二叉搜索树的后序遍历序列

难度 ⭐⭐

🎀 题目描述

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:
在这里插入图片描述
示例 1:

输入: [1,6,3,2,5] 输出: false

示例 2:

输入: [1,3,2,6,5] 输出: true

🎁 思路

这道题的思路是一个非常典型的树中的递归。由于这是一个后序遍历,每个向量的最后一个值就是二叉树的根节点。如果这的确是一个BST,那么整个向量应该分为[小于根节点的节点,大于根节点的节点]两部分,分别对应左、右孩子。否则,就不是BST。左、右孩子应该都为BST,整个树才为BST。这样,就构造出了递归算法。

class Solution {
public:
    bool verifyPostorder(vector<int>& postorder) {
        return verify(postorder,0,postorder.size()-1);
    }
    bool verify(vector<int>& postorder, int begin, int end){
        if(end-begin<=0) return true; //单个节点,必然是BST
        int root = postorder[end];
        int bigger = end; //第一个大于root的节点
        for(int i=begin;i<end;i++){
            if(postorder[i] > root){
                bigger = i;
                break;
            }
        }
        for(int i = bigger+1;i<end;i++){
            if(postorder[i] < root) //[1,6,3,2,5]
                return false;//不是BST
        }
        int left_begin = begin;
        int left_end = bigger-1;
        int right_begin = bigger;
        int right_end = end-1;
        return verify(postorder,left_begin,left_end) && verify(postorder,right_begin,right_end);//左右孩子都得是BST,整个才是BST
    }
};

在这里插入图片描述
和本题类似的题还有:

  • leetcode 98. 验证二叉搜索树
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值