一、二叉树
1.1 二叉树的基本结构
二叉树是由若干节点构成的结构,这些节点之间存在以下关系:
- 存在一个根节点
- 每个节点之多存在两个后继节点,分别称为左孩子和右孩子
- 任何地方均不存在环
1.2 二叉树的解题套路
树形DP,是指如果一个问题可以通过向左右子树分别要信息,再经过简单的组合就可拿到时。可采用的套路。具体步骤为:
- 思考如果想得到结果,我们需要想左右子树分别要什么信息?
- 通过左右子树的这些信息,我们怎么组合出父节点的相应信息,从而继续让上方的父节点调用?
例:判断一个二叉树是否为二叉搜索树
https://leetcode-cn.com/problems/validate-binary-search-tree/
二叉搜索树:任何一个节点的左子树中,只包含比他小的数;任何一个节点的右子树中,只包含比他大的数。
分析:
- 确认一棵树是二叉搜索树,我们需要拿到以下信息:第一,左右子树是不是都是二叉搜索树,根节点的值是否大于左子树的最大值,是否小于右子树的最小值。--> 需要的信息为:是否是二叉搜索树、最大值、最小值
- 如何根据左右子树的三个上述信息,得到整棵树的三个信息?
解答:
class ReturnData{
public long maxValue;
public long minValue;
public boolean isBST;
}
class Solution {
public boolean isValidBST(TreeNode root) {
return isBST(root).isBST;
}
public ReturnData isBST(TreeNode root){
if(root == null){
ReturnData returnData = new ReturnData();
returnData.minValue = Long.MAX_VALUE;
returnData.maxValue = Long.MIN_VALUE;
returnData.isBST = true;
return returnData;
}
ReturnData leftData = isBST(root.left);
ReturnData rightData = isBST(root.right);
ReturnData returnData = new ReturnData();
returnData.minValue = Math.min(Math.min(leftData.minValue, rightData.minValue), root.val);
returnData.maxValue = Math.max(Math.max(leftData.maxValue, rightData.maxValue), root.val);
returnData.isBST = (leftData.maxValue < root.val) && (rightData.minValue > root.val) && leftData.isBST && rightData.isBST;
return returnData;
}
}
例:判断一棵树是否是平衡二叉树
https://leetcode-cn.com/problems/balanced-binary-tree/
平衡二叉树:任何一个节点的左右子树深度差不超过1。
分析:所需信息为,是否为平衡二叉树,和深度。
解答:
class ReturnData{
public int depth;
public boolean isBST;
}
class Solution {
public boolean isBalanced(TreeNode root) {
return isBalancedTree(root).isBST;
}
public ReturnData isBalancedTree(TreeNode root){
ReturnData returnData = new ReturnData();
if(root == null){
returnData.depth = 0;
returnData.isBST = true;
}else{
ReturnData leftData = isBalancedTree(root.left);
ReturnData rightData = isBalancedTree(root.right);
returnData.depth = Math.max(leftData.depth, rightData.depth) + 1;
returnData.isBST = leftData.isBST && rightData.isBST && Math.abs(leftData.depth - rightData.depth) <= 1;
}
return returnData;
}
}
例:求两个节点的最低公共祖先
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/
解答:
class ReturnData {
public boolean containP;
public boolean containQ;
public TreeNode res;
}
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return getLCA(root, p, q).res;
}
public ReturnData getLCA(TreeNode root, TreeNode p, TreeNode q){
ReturnData returnData = new ReturnData();
if(root == null){
returnData.containP = false;
returnData.containQ = false;
returnData.res = null;
}
else{
ReturnData leftData = getLCA(root.left, p, q);
ReturnData rightData = getLCA(root.right, p, q);
if(leftData.res != null){
return leftData;
}
if(rightData.res != null){
return rightData;
}
returnData.containP = leftData.containP || rightData.containP || root == p;
returnData.containQ = leftData.containQ || rightData.containQ || root == q;
returnData.res = (returnData.containP && returnData.containQ) ? root : null;
}
return returnData;
}
}