二叉搜索树的后序遍历序列
一、需求
- 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果,如果是则返回
true
,否则返回false
。 - 假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:5/ \2 6/ \1 3
示例 1:输入: [1,6,3,2,5]
输出: false
示例 2:输入: [1,3,2,6,5]
输出: true
二、分治算法
2.1 思路分析
- 后序遍历:左、右、根。
- 二叉搜索树:左子树中所有结点的值 < 根结点的值,右子树中所有结点的值 > 根结点的值,其左、右子树也分别为二叉搜索树。
- 根据二叉树搜索树的定义,可以通过递归判断所有子树的正确性(即其后序遍历是否满足二叉搜索树的定义),若所有子树均正确,则此序列为二叉搜索树的后序遍历。
2.2 算法流程
- 终止条件:当 i >= j,说明此子树结点数量 <= 1,无需判别正确性,因此直接返回true;
- 递推工作:
1.划分左右子树:遍历后序遍历的[i, j]区间元素,寻找第一个大于根结点的结点,索引记为m,此时,可划分出左子树区间[i,m-1],右子树区间[m,j-1],根结点索引为 j 。
2.判断是否为二叉搜索树:
1.左子树区间[i,m-1]内的所有结点都应 < posterOrder[ j ] 。而在划分左右子树的步骤中,已经保证了左子树区间的正确性,因此,只需要判断右子树区间即可。
2.右子树区间[m,j-1]内的所有结点都应 > posterOrder[ j ] 。实现方式为遍历,当遇到 <= posterOrder[ j ]的结点跳出,通过判断p == j判断是否为二叉搜索树。
- 返回值:所有子树均正确才可判定正确,因此使用与逻辑符连接。
1.p == j:判断此树是否正确。
2.recur(i,m-1):判断此树的左子树是否正确。
3.recur(m,j-1):判断此树的右子树是否正确。
2.3 代码实现
class Solution {public boolean verifyPostorder(int[] postorder) {return recur(postorder,0,postorder.length - 1);}public boolean recur(int[] postorder,int i,int j) {if(i >= j) return true;int p = i;while(postorder[p] < postorder[j]) p++;int m = p;while(postorder[p] > postorder[j]) p++;return p == j && recur(postorder,i,m-1) && recur(postorder,m,j-1);}
}
2.4 复杂度分析
- 时间复杂度为O(N^2),每次调用recur(i,j)要减去一个根结点,因此递归占用O(N),最差情况下(当树退化为链表),每轮递归都需要遍历树的所有结点,占用O(N)。
- 空间复杂度为O(N),最差情况下(当树退化为链表),递归深度将达到N。
三、辅助单调栈
3.1 思路分析
- 后序遍历倒序:[根结点 | 右子树 | 左子树],类似于先序遍历的镜像,即先序遍历为"根、左、右"的顺序,而后序遍历的倒序为"根、右、左"。
- 设后序遍历倒序列表为
,遍历此列表,设索引为
,若为二叉搜索树,则有:
1.当结点值时,结点
一定是结点
的右子结点。
2.当结点值时,结点
一定是某结点root的左子结点,且root为结点
中值大于且最接近
的结点。
- 当遍历时遇到递减结点
,若为二叉搜索树,则对于后序遍历倒序中结点
右边的任意结点
,必有结点
。(结点
只可能为以下两种情况:①
为
的左、右子树的各结点;②
为root的父结点或更高层父结点的左子树的各结点。在二叉搜索树中,以上结点都应小于root。)
- 遍历"后序遍历的倒序"会多次遇到递减结点
,若所有的递减结点
对应的父结点root都满足以上条件,则可判定为二叉搜索树。
- 根据以上描述,考虑借助单调栈实现:
1.借助一个单调栈stack存储值递增的结点;
2.每当遇到值递减的结点,则通过出栈来更新结点
的父结点root;
3.每轮判定和root的值的关系:
1.若,说明不满足二叉搜索树的定义,直接返回false;
2.若,说明满足二叉搜索树的定义,则继续遍历。
3.2 算法流程
- 初始化:单调栈stack,父结点值
(初始值为正无穷大,可把树的根节点看为此无穷大节点的左孩子);
- 倒序遍历postorder:记每个结点为
;
1.判断:若,说明此后序遍历序列不满足二叉搜索树的定义,直接返回false;
2.更新父结点root:当栈不为空且时,循环执行出栈,并将出栈结点赋给root;
3.入栈:将当前结点入栈;
3.若遍历完成,说明后序遍历满足二叉搜索树的定义,返回true。
3.3 代码实现
class Solution {public boolean verifyPostorder(int[] postorder) {Stack<Integer> stack = new Stack<>();int root = Integer.MAX_VALUE;for(int i = postorder.length - 1; i >= 0; i--) {if(postorder[i] > root) return false;while(!stack.isEmpty() && stack.peek() > postorder[i]) {root = stack.pop();}stack.add(postorder[i]);}return true;}
}
3.4 复杂度分析
- 时间复杂度为O(N),各结点均出\入栈一次;
- 空间复杂度为O(N),最差情况下,单调栈所有结点。
四、参考地址
作者:Krahets
链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/solution/mian-shi-ti-33-er-cha-sou-suo-shu-de-hou-xu-bian-6/
二叉搜索树的后序遍历序列相关推荐
- 剑指offer:面试题33. 二叉搜索树的后序遍历序列
题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果.如果是则返回 true,否则返回 false.假设输入的数组的任意两个数字都互不相同. 参考以下这颗二叉搜 ...
- [剑指offer] 二叉搜索树的后序遍历序列
二叉搜索树的后序遍历序列 P157 题目:输入一个数组,判断这个数组是不是一个二叉搜索树的后序遍历的结果. solution:我们知道后序遍历序列的最后一个item是根节点,如果确实是二叉搜索树的后序 ...
- 剑指Offer - 九度1367 - 二叉搜索树的后序遍历序列
剑指Offer - 九度1367 - 二叉搜索树的后序遍历序列2013-11-23 03:16 题目描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出 ...
- C#刷剑指Offer | 二叉搜索树的后序遍历序列
[C#刷题]| 作者 / Edison Zhou 这是EdisonTalk的第289篇原创内容 我们来用之前学到的数据结构知识来刷<剑指Offer>的一些核心题目(精选了其中30+道题目) ...
- 【LeetCode】剑指 Offer 33. 二叉搜索树的后序遍历序列
[LeetCode]剑指 Offer 33. 二叉搜索树的后序遍历序列 文章目录 [LeetCode]剑指 Offer 33. 二叉搜索树的后序遍历序列 package offer;public cl ...
- 剑指offer——二叉搜索树的后序遍历序列
二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 这里遇到的问题就是,传递的子数组怎 ...
- 剑指offer——面试题24:二叉搜索树的后序遍历序列
剑指offer--面试题24:二叉搜索树的后序遍历序列 Solution1: 二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二 ...
- 剑指offer之二叉搜索树的后序遍历序列
剑指offer之二叉搜索树的后序遍历序列 欢迎关注作者博客 简书传送门 题目 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个 ...
- 剑指 Offer 33. 二叉搜索树的后序遍历序列
剑指 Offer 33. 二叉搜索树的后序遍历序列 原始题目链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian- ...
- 23.二叉搜索树的后序遍历序列
二叉搜索树的后序遍历序列 题目链接 题目描述 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 二叉搜索树 二 ...
最新文章
- lol服务器维护9月30,英雄联盟4月30日更新维护几点结束_4月30日LOL10.9版本停机维护结束时间_3DM网游...
- Jzoj5234 外星人的路径
- 解锁新姿势 | 如何用配置中心实现全局动态流控?
- 开源RefreshListView下拉刷新效果
- Qt中常用的QChar QByteArry QString数据类型转换方法
- isset、empty、var==null、is_null、var===null详细理解
- js把base64串解析成中文_26日大嘴足球:晚场5中3/中2串+1比分,早场(意甲+西甲)2场解析!!...
- 网络摄像机 c++ 抓拍_IP摄像机和工业摄像机怎么区分 IP摄像机和工业摄像机差异...
- socket可读,可写的条件
- 电视盒子做文件共享服务器,【当贝市场】智能电视盒子和PC电脑文件共享教程...
- 个人征信要良好,申请信用卡需注意哪些事项?
- 量化交易1-backtrader介绍
- (附源码)php酒店住宿管理系统 毕业设计 261455
- 美团{青龙面板可跑项目之一}保姆教程
- C语言利用顺序表求两个集合的差集
- java(反射机制)
- 1323: 三角形判定
- 索罗斯:走在时间前面的狐狸
- Linux top命令的了解以及使用
- 《关键对话》如何高效沟通,营造无往不利的事业和人生?
热门文章
- H3C W2612 瘦AP转胖AP笔记本刷机教程
- MSER最稳定极值区域源码分析
- springboot整合IPDB,获取地区信息
- ssis抽MySQL数据_SSIS探索之SSIS增量抽取数据
- AES加解密之ECB、CBC和CFB三种模式
- php+大于的特殊符号,CSS_网页制作基础知识:html特殊符号,一些特殊符(如小于号和大于 - phpStudy...
- python - 截取指定帧数间隔的视频,并保存图片到指定位置
- 计算机网络-网络层篇-ARP协议与RARP协议
- 算法设计与分析入门篇----贪心法3
- C语言成绩管理系统实例 附源码(一)