def verifyPostorder(postorder):
if postorder == None:
return True
return find(postorder,0,len(postorder)-1)
def find(order,i,j):
if i > j:
return True
root = order[j]
p = i
# 寻找order[:-1]中第一个大于root的位置
while order[p] < root:
p += 1
for __ in order[p:j]:
# 确保后面一部分所有节点不大于根结点
if __ < root:
return False
return find(order,i,p-1) and find(order,p,j-1)
class Solution:
def verifyPostorder(self, postorder: List[int]) -> bool:
def recur(leftindex,rootindex)->bool:
# leftindex为当前子树的左下标,rootindex为根下标
# 递归基
if leftindex>=rootindex:
return True
# 递归
for i in range(leftindex,rootindex+1):
# 找到第一个大于等于root的节点值所在index range函数是左闭右开的
if postorder[i]>=postorder[rootindex]:
break;
if i+1>=rootindex:
return recur(leftindex,i-1)
else:
for j in range(i,rootindex):
if postorder[j]<postorder[rootindex]:
return False
return recur(leftindex,i-1) and recur(i,rootindex-1)
return recur(0,len(postorder)-1)
class Solution:
def verifyPostorder(self, postorder: List[int]) -> bool:
# postorder=postorder[::-1]
stack=[]
parent=sys.maxsize
for i in range(len(postorder)-1,-1,-1):
while stack and postorder[i]<stack[len(stack)-1]:
parent=stack.pop()
if parent<postorder[i]:
return False
stack.append(postorder[i])
return True
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:
def recur(i, j):
if i >= j:
return True
p = i
while postorder[p] < postorder[j]:
p+=1
m = p
while postorder[p] > postorder[j]:
p+=1
return p j and recur(i, m-1) and recur(m, j-1)
class Solution {
public boolean verifyPostorder(int[] postorder) {
if (postorder == null) 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大的元素下标
while (postorder[p] < root) p++;
//找到p后,判断[p,j-1]中,是否有元素比root大,如果大,那就返回false,否则不返回,并且继续遍历
for (int k = p; k < j; k++) {
if (postorder[k] < root) return false;
}
return f(postorder , i , p - 1) && f(postorder , p , j - 1);
}
}
class Solution:
def verifyPostorder(self, postorder: List[int]) -> bool:
def recur(i, j):
if i >= j:
return True
p = i
while postorder[p] < postorder[j]:
p += 1
m = p
while postorder[p] > postorder[j]:
p += 1
return p == j and recur(i, m - 1) and recur(m, j - 1)
return recur(0, len(postorder) - 1)
class Solution:
def verifyPostorder(self, postorder: List[int]) -> bool:
def cur(i,j):
if i>=j:return True
p =i
while postorder[p]<postorder[j]:p+=1
m = p
while postorder[p]>postorder[j]:p+=1
return p==j and cur(i,m-1) and cur(m,p-1)
return cur(0,len(postorder)-1)
class Solution {
public boolean verifyPostorder(int[] postorder) {
if (postorder == null) {
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;
while (postorder[p] < root) {
p++;
}
for (int k = p; k < j ; k++) {
if (postorder[k] < root) {
return false;
}
}
return f(postorder, i, p - 1) && f(postorder, p, j - 1);
}
}
共以下 35 个回答
把握特点,右侧元素比中间元素大
递归,分辨校验左子树和右子树有且只有一个,只需要保证大于和小于根节点的区间是连续的且只有一个即可
时间O(N^2) 空间O(N)
//时间复杂度 O(n^2)
//空间复杂度 O(n)
解法一:递归+分治
序列最后的元素为root,从头至尾找到第一个大于root的元素right,如果从right到root之间存在小于root的元素,返回flase
否则从right左右两边分为两个子树进行判断。
解法二:单调栈
后序遍历为 左右中,其逆序是 中右左
这种逆序的遍历形象上很像是一种将树从右斜方从左上到右下一行行遍历的结果
如果栈空或者栈顶元素大于当前遍历的元素,压栈(说明是右子树),如果小于,弹栈直到栈顶元素大于遍历元素,最后一次弹出的元素就是当前元素的父节点(给parent存下来),在之后压栈中(因为前面进行弹栈操作了,所以右子树肯定是没有了,所以后面的元素不可能大于当前的parent值),一旦出现大于parent的值,就是错的。
根据上面的分析,最开始的parent需要默认设为int最大值,这样就可以将root节点的处理也包括进去了,不用特殊处理
第一种思路:根据二叉搜索树的特点和后序遍历的顺序。递归分治的思路。数组的最后一个元素就是根节点,找到大于根节点第一个值,在这个值之前的所有元素都小于这个值,在这个值之后的所有元素都大于这个值,这颗树就是二叉搜索树,再递归的判断左子树和右子树是不是二叉搜索树。时间复杂度最坏情况下是O(N^2),空间复杂度为O(N)。
第二种思路:单调栈。可是二叉搜索树的值顺序为右>中>左,后序遍历的顺序为左右中,没有单调性。可是后序遍历的逆序是中右左。有一定的单调性。时间和空间复杂度都为O(N)。
时间复杂度O(N^2)
空间复杂度O(N)
时间复杂度:O(n ^ 2)
空间复杂度:O(n)
思路:依次找这这棵数的左子树、右子树、根节点,并判断他们的顺序是否正确,如果正确,再进行子递归,继续重复判断
时间复杂度:O(N^2)
空间复杂度:O(N)
时间复杂度O(N^2)
空间复杂度O(n)
1、根据后序的特点,最后一个位置right是根。自左开始寻找第一个大于根的位置pos,判断其后是否仍有小于根的结点,若有则返回false。
2、再分别以pos-1为根(左子树)、right-1为根(右子树)进行递归。
3、时间O(n),空间O(n)
//递归分治& nums,int start,int end){
class Solution {
public:
bool fun(vector
if(start>=end) return true;
int target=nums[end];
int pos=start;
for(int i=start;i<=end;++i){
if(nums[i]<target) continue;
else{
pos=i;
break;
}
}
};
时间复杂度O(n)
空间复杂度O(n)
class Solution:
def verifyPostorder(self, postorder: List[int]) -> bool:
def recur(i, j):
if i >= j:
return True
p = i
while postorder[p] < postorder[j]:
p+=1
m = p
while postorder[p] > postorder[j]:
p+=1
return p j and recur(i, m-1) and recur(m, j-1)
递归的去判断,后序遍历中的最后一个节点是根节点,二叉搜索树又有左 > 右的特点,时间复杂度0n^2 空间复杂度on
解题思路:根节点为最后一个位置元素,遍历列表找到第一个大于根节点的位置,该位置之前的元素应都小于根节点,之后的元素都大于根节点,否则返回False,同事递归左右两个子树,完成求解。
时间复杂度:O(n2)
空间复杂度:O(n)
1.使用递归的方法
2.后序遍历最后一个为根节点,我觉得是关键
3.使用while语句可以得到第一个比根节点大的值
当数组顺序排列,时间复杂度O(n ^2)和空间复杂度O(n)都是最坏的
递归
时间O(n^2)
空间O(n)
注意函数传入vector容器的形参语法,二叉搜索树的概念
递归的思路还得多练呀,上道题看的迭代的写法,对二叉搜索树也不得行。找到左子树位置,子树也满足搜索树的要求,右子树也满足,建立递归终止条件,头和尾相交返回True,其他情况进行和头结点比对,还有一点就是对错误情况,右子树存在小于根结点的情况则是False
时间复杂度O(n^2),空间复杂度O(n)
时间复杂度O(N^2) 递归中遍历所有节点为N,最差情况下为链表,栈的递归深度为N
空间复杂度O(N),系统栈O(n)
递归
单调栈
时间:O(n),空间:O(n)