class Solution {
public boolean verifyPostorder(int[] postorder) {
return recur(postorder,0,postorder.length-1);
}
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);
}
}
class Solution:
def verifyPostorder(self, postorder: List[int]) -> bool:
return self.subTree(postorder, 0, len(postorder) - 1)
def subTree(self, postorder, l, r):
if l >= r:
return True
i = r
# 查找第一个比头结点大的节点,分出左右子树
for j in range(l, r):
if postorder[j] > postorder[i]:
i = j
break
# 查左右子树是否存在比头结点大或小的节点
for j in range(l, i):
if postorder[j] >= postorder[r]:
return False
for j in range(i, r):
if postorder[j] <= postorder[r]:
return False
# 递归
left = self.subTree(postorder, l, i - 1)
right = self.subTree(postorder, i, r - 1)
return left and right
class Solution {
public boolean verifyPostorder(int[] postorder) {
return recur(postorder, 0, postorder.length - 1);
}
private 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);
}
}
public boolean verifyPostorder(int[] postorder) {
return verifyPostorder(postorder, 0, postorder.length-1);
}
public boolean verifyPostorder(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 && verifyPostorder(postorder,i,m-1) && verifyPostorder(postorder,m,j-1);
}
class Solution:
def verifyPostorder(self, postorder: List[int]) -> bool:
def verifyPostorderHelper(i, j):
if i >= j:
return True
root = postorder[j]
p = i
while postorder[p] < root:
p += 1
for k in range(p, j):
if postorder[k] < root:
return False
return verifyPostorderHelper(i, p - 1) and verifyPostorderHelper(p, j - 1)
return verifyPostorderHelper(0, len(postorder) - 1)
class Solution {
public boolean verifyPostorder(int[] postorder) {
if (null == postorder) {
return true;
}
return f(postorder, 0, postorder.length - 1);
}
boolean f (int[] postorder, int i, int j) {
if (i >= j) {
return true;
}
int root = postorder[j];
int p = i;
// 找到第一个大于root的下标p
while (postorder[p] < root) p++;
// 判断p~j中是否存在小于root的值
for (int k = p; k < j; k++){
if (postorder[k] < root) {
return false;
}
}
// 递归左子树和右子树
return f(postorder, i, p-1) && f(postorder, p, j-1);
}
}
共以下 34 个回答
“`java stack = new Stack<>();
后序遍历和二叉搜索树的定义,二叉搜索树要从左到右依次变大,后序遍历根节点在最后,小于根节点的是左子树,大于根节点的是右子树
class Solution {
public boolean verifyTreeOrder(int[] postorder) {
if (postorder == null) {
return true;
}
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;
}
}
class Solution {
public boolean verifyPostorder(int[] postorder) {
if(postordernull){
return true;
}
return recur(postorder,0,postorder.length-1);
}
boolean recur(int[] postorder,int i,int j){
if(i>=j){
return true;
}
int n = i;
while(postorder[n]<postorder[j]){
n++;
}
for(int t=n;t<j;t++){
if(postorder[t]<postorder[j]){
return false;
}
}
return recur(postorder,i,n-1)&&recur(postorder,n,j-1);
}
}遍历
“`java
class Solution {
public boolean verifyPostorder(int[] postorder) {
if(postorder==null) return true;
}
关键是理解分解子问题
【思路】递归实现。对于一个preoder序列,最后一位即根节点,从前往后遍历,找到第一个比根节点大的元素,即左右子树的分界点,而后可以进一步拆分问题进行递归。
【时间复杂度】最差O(n^2)
【空间复杂度】最差O(n),即退化成链表
通过递归每次找到第一个比当前节点大的节点,此节点就是左右子树的分割点,再从左右子树中查看是否符合搜索树,然后再对其子树再进行此操作
函数的目标是验证给定的后序遍历序列是否是一个二叉搜索树的后序遍历序列。
函数首先检查postorder数组的大小,如果为0,则返回true。
然后调用辅助函数check来进行验证。check函数接受三个参数,即postorder数组、左边界l和右边界r。
在check函数中,首先判断左边界是否大于等于右边界,如果是,则返回true。
然后,获取当前子树的根节点的值,即postorder[r]。
接下来,使用两个指针i和j来遍历数组。指针i从左边界开始,向右移动,直到找到第一个大于根节点值的元素。指针j从指针i的位置开始,向右移动,直到找到第一个小于根节点值的元素。
如果指针j没有达到右边界,则说明存在一个大于根节点值的元素,不满足二叉搜索树的性质,返回false。
最后,递归调用check函数来验证左子树和右子树是否满足二叉搜索树的性质,即调用check(postorder, l, i-1)和check(postorder, i, j-1)。
如果左子树和右子树都满足二叉搜索树的性质,则返回true,否则返回false。
整个函数的时间复杂度为O(nlogn),其中n为数组postorder的长度。
复杂度
时间复杂度: $O(n^2)$
空间复杂度: $O(n)$
Code
时间和空间复杂度都是O(N)
思路:同时结合二叉搜索树和后序遍历序列的性质,判断序列中每课子树是否为二叉树
时间复杂度O(n) 空间复杂度O(n)
时间复杂度为O(nlogn)
空间复杂度为O(logn)。
递归
思路:把问题分解为子问题,数组中最后一位是根节点,应比左子树的值大,比右子树的值小。因此遍历数字,遇到第一个比根节点大的值视为右子树的开始,遍历右子树部分,如果有一个比根节点的值小,则返回false。但是讲解里的代码写法会更好点
时间复杂段:O(N^2)
空间复杂度:O(N)
参照leetcode评论区jyd的做法递归分治
时间:O(n^2)
空间:O(n)
c++实现& postorder,int start,int end)& postorder) {
bool traversal(vector
{
if(start>=end)return true;
int index = start;
while(postorder[index]<postorder[end])index++;
int midindex = index;
while(postorder[index]>postorder[end])index++;
bool left = traversal(postorder,start,midindex-1);
bool right = traversal(postorder,midindex,end-1);
return indexend&&left&&right;
}
bool verifyPostorder(vector
return traversal(postorder,0,postorder.size()-1);
}
看的参考答案的
python实现
C++实现
时间复杂度:O(n^2)
时空复杂度:O(n)
1、分析发现后续遍历的末尾元素为头结点,则以此进行划分,将数组第一个大于头结点的元素作为切分点,左边为左子树,其以及右边为右子树,再对右子树中是否存在小于当前头结点的数,有则返回false,没有则返回true,继续递归左右子树即可
通过从后往前遍历数组,模拟二叉树中右左的顺序,
平衡二叉树左小右大,所以借助辅助栈升序排放先存放父节点和后存右节点,如果当前结点小于辅助栈头结点则false否则将栈清空更新父节点
后序遍历:左右中
后序数组中的最后一个元素为根节点,其右子树要大于根节点的,从左向右遍历数组,找到第一个比根节点大的元素,以此为切割点,分为左子树和右子树;如果切割点的右侧存在比根节点小的元素,返回false,否则按照此规律一层一层递归分割好的数组。
C++实现:& postorder, int begin, int end)
class Solution {
public:
bool verify(vector
{
if(begin >= end) return true;
int root = postorder[end];
//设置分界点
int mid = begin;
while(postorder[mid] < root)
{
mid++;
}
int temp = mid;
};
O(n^2)时间复杂度
O(n) 空间复杂度 退化成链表
复杂度O(n^2)
MY