三个题目都有着相似的思想!都是需要首先对于当前出发的子节点的结构是否满足对应的性质,然后递归判断当前的树中的剩余的节点是否满足!
树的子结构的代码
class Solution {
public:
bool isSubStructure(TreeNode* A, TreeNode* B) {
if(!A && !B) return true;
if(A == NULL || B == NULL) return false;
return dfs(A, B) || isSubStructure(A->left, B) || isSubStructure(A->right, B);
}
bool dfs(TreeNode* A, TreeNode* B) {
if(B == NULL) return true;
if(A == NULL) return false;
return A->val == B -> val && dfs(A->left, B->left) && dfs(A->right, B->right);
}
};
其中dfs的函数中,是判断当前出发的节点与对应的树中的节点是否满足完全相同的性质!相同的话就是应该满足当前节点的取值相等,对应的左子树相等,右子树相等!
然后再判断的函数中,首先是判断当前节点的子树是否满足,然后再后面递归求解剩余节点是否满足!主要是明白这里性质!
检查子树:
class Solution {
public:
bool checkSubTree(TreeNode* t1, TreeNode* t2) {
if(!t1) return false;
if(t1 && !t2 ) return true;
return checkTree(t1, t2) || checkSubTree(t1->left, t2) || checkSubTree(t1->right, t2);
}
//上面的return的函数可以理解为对应的每个节点是首先判断是否成立,然后再递归的去判断后续的子树
//是否成立的方法!所以调用的时候必须是先判断当前是否成立,然后再判断后面的节点是否成立的!
bool checkTree(TreeNode* t1, TreeNode* t2) {
if(t2 == NULL) return true;
if(t1 == NULL) return false;
if((!t1 && t2)||(t1 && !t2)) return false;
return t1 -> val == t2 -> val && checkTree(t1 -> left, t2 -> left) && checkTree(t1 -> right, t2 -> right);
}
};
与上面思路完全一样的!还是要明白第二个函数是用来判断当前节点出发产生的子树是否与t2子树完全相同,然后再第一个函数中首先应该是判断是否相等,然后再递归判断后续的节点产生的子树是否也满足性质!
求和路径的问题:
class Solution {
public:
int pathSum(TreeNode* root, int sum) {
if(!root) return 0;
return getSum(root, sum) + pathSum(root -> left, sum) + pathSum(root -> right, sum);
}
//确实跟前面的判断是否为子树的问题相似,当前节点是否满足,后续的遍历全部节点是否满足即可!
//同时在实现的时候思路完全相同的,只是修改为对应的值的减少和增加问题。
int getSum(TreeNode* root, int sum ) {
if(!root) return 0;
sum -= root -> val;
return sum == 0 ? 1 : 0 + getSum(root -> left, sum) + getSum(root -> right, sum);
}
};
思路相同的,只是需要修改判断的流程,当sum的值为0 的时候对应的则可以为满足加一,否则继续判断下去,然后再第一个函数中,应该是首先判断当前的节点出发的子树是否满足性质,然后再依次遍历对应的节点去判断是否满足!
递归还在努力理解中…