前面聊了一系列关于链表相交的问题,本篇博文,让我们通过一道简单的判断题,复习复习数组和二叉树。
通过这道题,你可以掌握
- 二叉查找树的规律
- 后序遍历的特点
- 递归的使用
题目
输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。
如果是返回 true,否则返回 false。
例如输入 5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果:
因此返回 true。
如果输入 7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回 false。
看到二元查找树(or二叉查找树),第一反应,
比根结点大的数在右边,比根结点小的数在左边 接着看到后序查找,第一反应,
最后遍历到的数是根结点 做到这两点,此题就没什么难度了,就当过个编程瘾。当然在一些难度较大的题目,光是发现这两个规律是不够的。
思路 因为是后续遍历,那么最后遍历到的数是根结点。
又因为是二叉查找树,所以比根结点大的数在右边,比根结点小的数在左边,
左边的数遍历比右边的较快被遍历到!
所以必须满足
比根结点大的数中最小角标 比 比根结点小的数中最大角标 要大!
对左右子数组同样使用上面的思路进行递归判断!
如果数组的长度小于等于3,则不需判断,肯定满足
源代码
#include <stdio.h>
#include<stdlib.h>
#include <iostream>
#include<sstream>
#include <vector>
using namespace std;
/**
题目:
输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。
如果是返回 true,否则返回 false。
思路
如果是后续遍历,那么最后遍历到的数是根结点。
又因为是二叉查找树,所以比根结点大的数在右边,比根结点小的数在左边,
左边的数遍历比右边的较快被遍历到!
所以必须满足比根结点大的数中最小角标 比 比根结点小的数中最大角标 要大!
对子数组同样使用上面的思路进行递归判断!
如果子数组的长度小于等于3,则不需判断,肯定满足
*/
/**
ifBTreeHouXu
vt 给一个vector数组,判断是否是后序遍历结果
*/
bool ifBTreeHouXu(vector<int> vt){
if(vt.size()<=0||NULL== &vt)
return false;
if(vt.size()>3){//如果子数组的长度小于等于3,则不需判断,肯定满足
int root = vt[vt.size()-1];//获取根结点值
bool flag = true;
vt.pop_back();//剔除根结点
vector<int> vt_small;//小于根结点的数组
vector<int> vt_big;//大于根结点的数组
//遍历
for(int i = 0;i<vt.size();i++){
//如果遍历到一个数比根结点大,则把flag置为false
//下面如果再遍历到一个数比根结点小,则说明该数组不是后序遍历结果
if(flag&&vt[i]>root)
flag=false;
else if(flag&&vt[i]<root)
vt_small.push_back(vt[i]);
else if(!flag&&vt[i]>root)
vt_big.push_back(vt[i]);
else
return false;//此数组不是后序遍历结果
}
return ifBTreeHouXu(vt_small)&&ifBTreeHouXu(vt_big);
}
return true;
}
vector<int> vt_test;
void initTure(){
vt_test.push_back(5);
vt_test.push_back(7);
vt_test.push_back(6);
vt_test.push_back(9);
vt_test.push_back(11);
vt_test.push_back(10);
vt_test.push_back(8);
}
void initFalse(){
vt_test.push_back(7);
vt_test.push_back(4);
vt_test.push_back(6);
vt_test.push_back(5);
}
void main()
{
initTure();
//initFalse();
if(ifBTreeHouXu(vt_test))
cout<<"是后序遍历结果"<<endl;
else
cout<<"【不】是后序遍历结果"<<endl;
system("pause");
}
运行图
总结:
二元查找树,第一反应,比根结点大的数在右边,比根结点小的数在左边
后序查找,第一反应,最后遍历到的数是根结点