每日一算法题-二叉搜索树

116 阅读1分钟

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

一、题目

描述:
给定一个二叉树根节点,请你判断这棵树是不是二叉搜索树。
二叉搜索树满足每个节点的左子树上的所有节点均严格小于当前节点且右子树上的所有节点均严格大于当前节点。

image.png

#include<iostream>
using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    inline TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

bool isValidBST(TreeNode* root) {
}

int main(int, char*[])
{
    TreeNode root(2);
    TreeNode node1(1);
    TreeNode node2(3);
    root.left = &node1;
    root.right = &node2;

    cout << (isValidBST(&root) ? "是二叉搜索树" : "不是二叉搜索树") << endl;
}

二、分析

这道题的陷阱是:
左子树上所有节点都要小于自己,比如左子树的右子树要比左子树大但要比自己小。
右子树上所有节点都要大于自己,比如右子树的左子树要比右子树小但要比自己大。
而且在迭代过程中,也不可能每一层都返回去和根节点做比较。

解题关键,观察规律。

由上诉描述可知,比较顺序为左子树<自己<右子树,这个和中序遍历有着异曲同工之妙,因为中序遍历就可以保证遍历左子树的时候最后一个访问的节点是左子树的右子树,遍历右子树的时候最后一个访问的节点是右子树的左子树,恰恰解决了陷阱。

实现的时候有一个点需要注意,我们需要一个临时变量,遍历到哪里就需要把哪里的值给复制下来给下一次遍历的时候比较使用,为了减少开销,我采取指针引用的形式,虽然这里传的是int,和指针的开销差不多,但是这是一个好习惯。

三、模拟

  1. 2 -> 1
  2. 1 < 2
  3. 2 -> 3
  4. 3 > 2

四、实现

inline bool isValidBSTInline(TreeNode* root, int* &reference){
    if(!root) return true;
    if((root->left && !isValidBSTInline(root->left, reference)) || (reference && root->val <= *reference)) return false;
    reference = &root->val;
    if(root->right && !isValidBSTInline(root->right, reference)) return false;
    return true;
}
bool isValidBST(TreeNode* root) {
    int* null = nullptr;
    return isValidBSTInline(root, null);
}

五、结言

这道题考验的就是对二叉树中序遍历的掌握程度,也是一道经典的实用题型。

创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!