递归的中序遍历,动态的进行比较
class lei():
def __init__(self):
self.prevalue=-float('inf') #负无穷
def fun1(self,root):#递归形式的中序遍历
if root==None: #基本结束条件
return True #说明是正常结束
bool1=self.fun1(root.left) #看左子树是否为正常的
if not bool1:
return False
if self.prevalue<root.val:
self.prevalue=root.val
else:
return False
return self.fun1(root.right)
不动态进行比较,全部入数组,在递归结束后统一进行比较,是非常稳妥的方法
class Solution:
def isValidBST(self, root) -> bool:
ls=[]
def fun2(root,ls):
if root==None:
return
fun2(root.left,ls)
ls.append(root.val)
fun2(root.right,ls)
fun2(root,ls)
for i in range(len(ls)-1):
if ls[i]>=ls[i+1]:
return False
return True
非递归代码,对于我现在而言比较简单,相对递归代码动态比较也更为容易
def fun3(root):
pre=-float('inf') #上一个节点的大小,对于中序遍历应该是一样的
stack=[]
while stack or root: #只要有一个不为空就可以进来
while root:
stack.append(root) #当前节点入栈
root=root.left
root=stack.pop()
if pre>=root.val:
return False
else:
pre=root.val
root=root.right
return True
树形动态规划
动态规划,在具有大量重复计算,或后序步骤可以使用前面结果,并且随着代码的运行前面的,结果不会改变的时候进行使用的一种方法
那么这个题目
如果我知道了一个节点的两个子树的相关信息,如是否为二叉搜索树,对应的最大值,最小值那么相应的结果就可以出来了
def main4(root):
return fun4(root)[0]
def fun4(x):
'''
分治思想
如果我要搞一个搜索二叉树,肯定是这个样子
1.对于任意节点,我的左子树要是搜索二叉树
2.对于任意节点,我的右子树要是搜索二叉树
3.对于任意节点,我的左子树的所有值要小于该节点的值(即左子树最大值小于该节点的值)
4.对于任意节点,我的右子树的所有值要大于该节点的值(即右子树最小值大于该节点的值)
:param x:
:return:
'''
if x==None:
return None #是搜索二叉树,要单独讨论叶节点的问题
dui1=fun4(x.left) #是否为二叉搜索树,最小值,最大值
dui2=fun4(x.right)
if dui1 and dui2:#都不空
fhz=dui1[0] and dui2[0] and dui1[2]<x.val and dui2[1]>x.val
z=dui1[1]
y=dui2[2]
return fhz,z,y
elif dui1 and (not dui2): #只有左子树,没有右子树
fhz=dui1[0] and dui1[2]<x.val
z=dui1[1]
y=x.val
return fhz,z,y
elif (not dui1) and dui2:
fhz=dui2[0] and dui2[1]>x.val
z=x.val
y=dui2[2]
return fhz,z,y
else:#都没有
return True,x.val,x.val
树形动态规划
'''
我上面代码虽然通过了,但在这里写的应该有些问题
fhz=dui1[0] and dui2[0] and dui1[2]<x.val and dui2[1]>x.val
z=dui1[1]
y=dui2[2]
return fhz,z,y
如果这样写,我返回的z和y不一定是该树的最小,最大值
但是想想代码为什么可以通过,因为我的<<"错误">>是不断累积的
如果在有一次的递归过程中,我得到了fhz为False,假设他为第一次,那么一定是在这一次之后(包括这一次)返回的最大,最小有问题
而在后面的过程中,因为False起着关键性的作用,所以最大,最小值就不在这么重要了
即:如果始终为True那么最大最小始终是对的
如果变为False,则不需要最大最小值
'''
def main5(root):
return fun4(root)[0]
def fun5(x):
'''
分治思想
如果我要搞一个搜索二叉树,肯定是这个样子
1.对于任意节点,我的左子树要是搜索二叉树
2.对于任意节点,我的右子树要是搜索二叉树
3.对于任意节点,我的左子树的所有值要小于该节点的值(即左子树最大值小于该节点的值)
4.对于任意节点,我的右子树的所有值要大于该节点的值(即右子树最小值大于该节点的值)
:param x:
:return:
'''
if x==None:
return None #是搜索二叉树,要单独讨论叶节点的问题
dui1=fun5(x.left) #是否为二叉搜索树,最小值,最大值
dui2=fun5(x.right)
if dui1 and dui2:#都不空
fhz=dui1[0] and dui2[0] and dui1[2]<x.val and dui2[1]>x.val
z=min(dui1[1],x.val)
y=max(dui2[2],x.val)
return fhz,z,y
elif dui1 and (not dui2): #只有左子树,没有右子树
fhz=dui1[0] and dui1[2]<x.val
z=min(dui1[1],x.val)
y=x.val
return fhz,z,y
elif (not dui1) and dui2:
fhz=dui2[0] and dui2[1]>x.val
z=x.val
y=max(dui2[2],dui2[2])
return fhz,z,y
else:#都没有
return True,x.val,x.val