C++版 - 剑指offer 面试题24:二叉搜索树BST的后序遍历序列(的判断) 题解
剑指offer 面试题24:二叉搜索树的后序遍历序列(的判断)
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true。否则返回false。假设输入的数组的任意两个数字都互不相同。
提交网址: http://www.nowcoder.com/practice/a861533d45854474ac791d90e447bafd?tpId=13&tqId=11176
二叉搜索树(英语:Binary Search Tree),也称二叉查找树、有序二叉树(英语:ordered binary tree),排序二叉树(英语:sorted binary tree),是指一棵空树或者具有下列性质的二叉树:
- 任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 任意节点的左、右子树也分别为二叉查找树;
- 没有键值相等的节点。
二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低。为O(log n)。二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。
二叉查找树的查找过程和次优二叉树类似,通常采取二叉链表作为二叉查找树的存储结构。中序遍历二叉查找树可得到一个关键字的有序序列,一个无序序列可以通过构造一棵二叉查找树变成一个有序序列,构造树的过程即为对无序序列进行查找的过程。每次插入的新的结点都是二叉查找树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索、插入、删除的复杂度等于树高,期望O(log n),最坏O(n)(数列有序,树退化成线性表)。
虽然二叉查找树的最坏效率是O(n),但它支持动态查询,且有很多改进版的二叉查找树可以使树高为O(log n), 如SBT、AVL树、红黑树。故不失为一种好的动态查找方法。
对于二叉搜索树BST,在树中任取一棵子树,其节点值都满足:左结点的值 < 父节点的值 < 右结点的值,故如果按照中序遍历的顺序遍历一棵二叉搜索树BST,遍历序列的数值是递增排序的。只需要用中序遍历算法遍历一棵二叉搜索树BST,就可以找出它的第k大结点。
1. 递归解法
由题意,可以将输入序列划分为3部分,即left、right、root,首先找到left部分最后一个结点的下标,即可完成分隔。如果left部分和right部分均是BST,即可递归调用VerifySquenceOfBST( )函数,变量bleft记录left部分是否为BST,bright记录right部分是否为BST。i从0~len-1对所有结点遍历一次... 最后的bleft&&bright即为所求的值。
6
/ \
3 8
/ \ / \
2 5 7 9
AC代码:
#include<cstdio>
#include<vector>
using namespace std;
class Solution{
public:
bool VerifySquenceOfBST(vector<int> sequence)
{
int len=sequence.size();
if(len<=0) return false;
vector<int> left, right;
int root=sequence[len-1];
int i=0;
while(i<len-1) // 处理left部分
{
if(sequence[i]>root) break;
left.push_back(sequence[i]);
i++;
}
int j=i; // 处理right部分,此时i为left部分最后一个结点的下标
while(j<len-1)
{
if(sequence[j]<root) return false;
right.push_back(sequence[j]);
j++;
}
bool bleft=true; // 应初始化为true,left部分是BST序列,才能调用VerifySquenceOfBST()
if(i != 0) bleft=VerifySquenceOfBST(left); // i为left部分最后一个结点的下标 ,i!=0表示有左子树
bool bright=true;
if(i != len-1) bright=VerifySquenceOfBST(right); // i!= len-1表示有右子树
return (bleft && bright);
}
};
// 以下为测试部分
int main()
{
Solution sol;
vector<int> vec1={2,5,3,7,9,8,6};
vector<int> vec2={5,7,6,9,11,10,8};
vector<int> vec3={7,4,6,5};
bool res1=sol.VerifySquenceOfBST(vec1);
bool res2=sol.VerifySquenceOfBST(vec2);
bool res3=sol.VerifySquenceOfBST(vec3);
printf("%d\n",res1);
printf("%d\n",res2);
printf("%d\n",res3);
return 0;
}
2. 非递归解法
左子树一定比右子树小,因此去掉根结点后,数字分为left,right两部分,right部分的最后一个数字是右子树的根,且它比左子树所有结点的值大,因此我们可以每次只看有子树是否符合条件即可,即使到达了左子树,左子树也可以看出由左右子树组成的树还像右子树那样处理.
对于左子树回到了原问题,对于右子树,左子树的所有值都比右子树的根小,可以暂时把他看出右子树的左子树,只需看看右子树的右子树是否符合要求即可.
例A:
6
/ \
3 8
/ \ / \
2 5 7 9
2 5 3 7 9 8 6
f -------------b
f -----------b
f --------b
f ------b
AC代码:
#include<cstdio>
#include<vector>
using namespace std;
class Solution
{
public:
bool VerifySquenceOfBST(vector<int> sequence)
{
int backIdx = sequence.size();
if(backIdx==0) return false;
int forIdx = 0;
while(--backIdx) // backIdx=1时退出循环
{
while(sequence[forIdx]<sequence[backIdx]) forIdx++; // forIdx从前往后扫描left部分
while(sequence[forIdx]>sequence[backIdx]) forIdx++; // forIdx从前往后继续扫描,主要扫right部分
if(forIdx<backIdx) return false; // 如果原序列是二叉搜索树BST的后序遍历序列,则终止时forIdx=backIdx
forIdx=0; // 将forIdx拉回序列起点继续扫
}
return true;
}
};
// 以下为测试部分
int main()
{
Solution sol;
vector<int> vec1={2,5,3,7,9,8,6};
vector<int> vec2={5,7,6,9,11,10,8};
vector<int> vec3={7,4,6,5};
bool res1=sol.VerifySquenceOfBST(vec1);
bool res2=sol.VerifySquenceOfBST(vec2);
bool res3=sol.VerifySquenceOfBST(vec3);
printf("%d\n",res1);
printf("%d\n",res2);
printf("%d\n",res3);
return 0;
}
将此代码结合例A思考,还是不难理解的...
C++版 - 剑指offer 面试题24:二叉搜索树BST的后序遍历序列(的判断) 题解的更多相关文章
- 剑指Offer:面试题24——二叉搜索树的后序遍历序列(java实现)
问题描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 思路: 1.首先后序遍历的结果是[(左子 ...
- C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解
剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...
- 剑指Offer:面试题27——二叉搜索树与双向链表(java实现)
问题描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路: 将树分为三部分:左子树,根结点,右子树. 1.我们要把根结点与左 ...
- 剑指offer 面试题36.二叉搜索树与双向链表
中序递归,一个pre节点记录前一个节点 /* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; Tre ...
- 剑指Offer - 九度1503 - 二叉搜索树与双向链表
剑指Offer - 九度1503 - 二叉搜索树与双向链表2014-02-05 23:39 题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树 ...
- 剑指Offer - 九度1367 - 二叉搜索树的后序遍历序列
剑指Offer - 九度1367 - 二叉搜索树的后序遍历序列2013-11-23 03:16 题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出 ...
- C++版 - 剑指offer 面试题22:栈的压入、弹出序列 题解
剑指offer 面试题22:栈的压入.弹出序列 提交网址: http://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId ...
- 剑指offer(23)二叉搜索树的后序遍历序列
题目描述 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 题目分析 1.后续遍历我们可以知道,最右边的是根节 ...
- 剑指offer(20)二叉搜索树与双向表
题目: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 思路一:递归法 1.将左子树构造成双链表,并返回链表头节点. 2.定位至左子 ...
随机推荐
- ACM(图论)——tarjan算法详解
---恢复内容开始--- tarjan算法介绍: 一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法.通过变形,其亦可以求解无向图问题 桥: 割点: 连通分量: 适用问题: 求 ...
- java pdf转word 高效不失真
将java工程导成jar包 使用 bat 执行 jar 包. --------------------------------------------------------------------- ...
- window环境下修改postgrep密码
本机window7 64位系统,安装的PostgreSQL 9.3 默认安装是没有设置密码的,使用pgAdmin III登陆需要登陆密码. 我们使用默认安装的工具 SQL Shell 来操作. 我们依 ...
- docker私库Harbor部署(转载)
系统环境 centos7.3docker-ce docker version: 18.03.0docker-compose version: 1.21.0 Install Docker CE 安装依赖 ...
- 记录一下maven使用过程中的问题
Failed to execute goal on project bos_fore: Could not resolve dependencies for project 上面问题,我把<de ...
- jenkins maven git windows code 自动部署
本人刚刚接触 写的不好就对付看看吧 哈哈哈O(∩_∩)O哈哈~ 最近看见别人弄得自动部署 自己也是手痒痒 也想弄一个 所以就弄了一个 windows的 我用的是https的 在网上看了很多都是 s ...
- lwip协议栈学习---udp
书籍:<嵌入式网络那些事-lwip协议> udp协议的优点: 1)基于IP协议,无连接的用户数据报协议,适用于传送大批量数据, 2)实时性比较高,适用于嵌入式网络 发送函数:udp_sen ...
- ACM计划
原文 :http://027xbc.blog.163.com/blog/static/128159658201141371343475/ ACM主要是考算法的,主要时间是花在思考算法上,不是花在写程序 ...
- 利用Socket 实现多客户端的请求与响应
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class Serve ...
- Python之旅Day15 Bootstrap与Django初识
Bootstrap初识 Bootstrap简介 Bootstrap 是最受欢迎的 HTML.CSS 和 JS 框架,用于开发响应式布局.移动设备优先的 WEB 项目.(官网http://www.boo ...