题目
检查一颗二叉树是否为二叉搜索树
思路
首先,什么是二叉搜索树?
二叉搜索树左子树中任意节点值小于根节点;右子树中任意节点值大于根节点;左右子树都必须是二叉查找树,不允许存在重复节点。
不过这里还有一点需要注意。让我们看下面这棵树。
尽管每个节点都比左子节点大,比右子节点小,但这并不是一棵二叉搜索树。其中8的位置不对,比根节点6要大。
更准确地说,成为二叉搜索树的条件是:所有左边的节点必须小于当前节点,而当前节点必须小于所有右边节点。
利用这一点,我们可以通过自上而下传递最小和最大值来解决这个问题。在迭代遍历整个树的过程中,我们会用逐渐变窄的范围来检查各个节点。
实现
#include <cstdio>
#include "BinaryTree.h"
#include <iostream>
using namespace std;
bool IsSearchTree(const BinaryTreeNode* pRoot, int min, int max)
{
if (pRoot == nullptr)
return true;
if (pRoot->m_nValue < min || pRoot->m_nValue >= max)
return false;
// 进入左子树时,更新max;进入右子树时,更新min
// 如果任一节点不能通过检查,则停止并返回false
if (!IsSearchTree(pRoot->m_pLeft, min, pRoot->m_nValue) || !IsSearchTree(pRoot
->m_pRight, pRoot->m_nValue, max))
return false;
return true;
}
// 测试代码
// 二叉查找树
// 6
// / \
// 3 9
// /\ / \
// 2 8 7 10
bool Test()
{
BinaryTreeNode* pNode1 = CreateBinaryTreeNode(6);
BinaryTreeNode* pNode2 = CreateBinaryTreeNode(3);
BinaryTreeNode* pNode3 = CreateBinaryTreeNode(9);
BinaryTreeNode* pNode4 = CreateBinaryTreeNode(2);
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNode6 = CreateBinaryTreeNode(7);
BinaryTreeNode* pNode7 = CreateBinaryTreeNode(10);
ConnectTreeNodes(pNode1, pNode2, pNode3);
ConnectTreeNodes(pNode2, pNode4, pNode5);
ConnectTreeNodes(pNode3, pNode6, pNode7);
// Integer_min = 0x80000000
// Integer_max = 0x7fffffff
bool flag = IsSearchTree(pNode1, 0x80000000, 0x7fffffff);
return flag;
}
int main()
{
bool flag = Test();
cout << flag << endl;
return 0;
}复制代码
该解法的时间复杂度是O (N ), 其中N 为整棵树的节点数。我们可以证明这已经是最佳做法,因为任何算法都必须访问全部N 个结点。
因为用了递归,对于平衡树,空间复杂度是O (logN )。在调用栈上,共有O (logN )个递归调用,因为递归的深度最大会到这棵树的深度。
记住,在递归算法中,一定要确定终止条件以及节点为空的情况得到妥善处理。
参考文献
[1] C++中整数最值的表示方法
[2] 《程序员面试金典》