树型动态规划
判断一个树是否是一个搜索二叉树。(所有树的节点的左节点比头结点小,所有树的右节点比头结点大)。
如果不按树型的动态规划套路来的话,我们可以用前序遍历,然后得到一个队列,判断这个队列是否递增来判断。也可以在前序遍历的递归写法里,判断。
但是如果按树型的动态规划套路来的话。我们可以假设左节点能返回信息,右节点也能返回一个信息。
那么我们需要左节点返回的信息是左节点是否是搜索二叉树,左节点的最大值。
那么我们需要右节点返回的信息是右节点是否是搜索二叉树,右节点的最小值。
那么合并后,我们知道我们只需要写个递归体,返回的结构是(是否二叉树,最大值,最小值)。
而头结点的返回构造,是否是二叉树需要满足,左节点是二叉树,且右节点是二叉树。头结点的值比左节点的最大值大,比右节点的最小值小。
这样,我们递归完,就能获取整棵树的所有节点对应的结构体。
5(true,2,7)
4 (true,2,4) 7(true,6,7)
2(true,null,null) 3(true,null,null) 6(true,null,null)
有没有感觉,这不就是动态规划.
只不过是递归的动态规划。
其实我们可以换个思路看,不就是树倒过来,从叶子节点往上推。先计算了2的结构体,然后3的结构体,因此可以推出4的结构体,而5的结构体需要7的结构体推,7需要6,这样就从叶子节点倒逼网上递归了。
在按这个套路来讨论下
判断一个树是否是平衡二叉树。(所有数的节点的左高度与右高度差小于1)。
但是如果按树型的动态规划套路来的话。我们可以假设左节点能返回信息,右节点也能返回一个信息。
那么我们需要左节点返回的信息是左节点是否是平衡二叉树,树的高度。
那么我们需要右节点返回的信息是右节点是否是平衡二叉树,树的高度。
那么合并后,我们知道我们只需要写个递归体,返回的结构是(是否平衡二叉树,树的高度)。
而头结点的返回构造,是否是平衡二叉树需要满足,左节点是平衡二叉树,且右节点是平衡二叉树。左树的高度与右树的高度差小于1.
这样,我们递归完,就能获取整棵树的所有节点对应的结构体。
在想一下
给定两个二叉树的节点,node1和node2,找到他们的最低公共祖先节点。
当然我们可以宽度遍历,然后用一个map存储每个节点的对应的父节点的对应关系。然后,node1按map找到所有的祖先节点放入set,然后node2按map找祖先节点,找重复的。这个是比较能理解的想法。
那么我们可以用树的动态规划套路来做吗。
如果按树型的动态规划套路来的话。我们可以假设左节点能返回信息,右节点也能返回一个信息。
那么我们需要左节点返回的信息是(是否node1的父节点,是否是node2的父节点,最低公共祖先节点)
那么我们需要右节点返回的信息是(是否node1的父节点,是否是node2的父节点,最低公共祖先节点)
那么合并后,我们知道我们只需要写个递归体,返回的结构是(是否node1的父节点,是否是node2的父节点,最低公共祖先节点)。
而头结点的返回构造,
是否node1的父节点 看头结点是否是node1,看左节点是node1的父节点吗,看右节点是node1的父节点吗,有一个满足就是。否则不是。
是否node2的父节点 看头结点是否是node2,看左节点是node2的父节点吗,看右节点是node2的父节点吗,有一个满足就是。否则不是。
最低公共祖先节点,如果头结点是node1的头结点,也是node2的头结点,那么塞入本节点。否则就是左右节点的两个值。
这样,我们递归完,就能获取整棵树的所有节点对应的结构体。
当然,后续优化发现,不需要这么多信息,只需要,返回node,node是(遇到node1返回node1,遇到node2返回node2)。但是不好理解。
我们可以知道,其实这个思路就是从叶子节点,往上动态规划。这样就可以拿到最终整棵树的所欲结构体。