不同于正常的编程方式,递归编程要求函数的自身调用,这就引发了一种“错觉”,想实现一个功能A,却要用功能A已经实现后去实现该功能A。这个部分可以被称为“递归的点”,也是递归问题的难点。
看下面这个例题,判断一个二叉树是不是镜像对称的二叉树。
//定义树节点
struct TreeNode{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int a){data=a;left=NULL;right=NULL;};
};
//判断是否为对称二叉树,输入二叉树的根节点
bool isSymmetric(TreeNode* root) {
return boolValue;
}
面对递归的问题,我们应该逐步分析,直到找到“递归的点”:
1、寻找递归出口:递归出口是指明确的递归结束条件,一般为为0或者1、空树这种预先定义好的初始情况,本题中当根节点为空时或者左子树和右子树为空时,为对称二叉树
2、考虑非特殊情况:当根结点、左子树和右子树都不为空时,如果左子树和右子树对称,则为对称二叉树
3、如何判断左子树和右子树对不对称?当左子树的左孩子和右子树的右孩子对称,左子树的右孩子和右子树的左孩子对称都满足时,左子树和右子树对称
这里对于对称的定义是一种递归的定义,就是我们要找的“递归的点”,找到“递归的点”我们就可以开始设计递归函数了。
对称的返回结果是一种bool型,输入值是左子树和右子树的根节点,所以对于对称的递归函数定义我们可以定义为
//该函数定义结构与题目要求的isSymmertic函数不一样,该递归函数为isSymmertic函数的辅助函数
bool helper(TreeNode *l,TreeNode *r){
return boolValue;
}
则原函数被改造为
//定义树节点
struct TreeNode{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int a){data=a;left=NULL;right=NULL;};
};
//判断是否为对称二叉树,输入二叉树的根节点
bool helper(TreeNode *l,TreeNode *r){
return boolValue;
}
bool isSymmetric(TreeNode* root) {
return helper(root->left, root->right);
}
1、寻找递归出口:
//定义树节点
struct TreeNode{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int a){data=a;left=NULL;right=NULL;};
};
//判断是否为对称二叉树,输入二叉树的根节点
bool helper(TreeNode *l,TreeNode *r){
if(l==NULL&&r==NULL) return true; //只有根节点的递归出口,判断为对称二叉树
return boolValue;
}
bool isSymmetric(TreeNode* root) {
if(root==NULL) return true; //没有根节点的空树,也判断为对称二叉树
return helper(root->left, root->right);
}
2、考虑非特殊情况:
先考虑下不用递归的非特殊情况,最简单的一种非特殊情况就是左子树的根节点和右子树的根节点只包含一个,这样必定是false,或者当前左右子树的根节点值都不相同,返回false
//定义树节点
struct TreeNode{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int a){data=a;left=NULL;right=NULL;};
};
//判断是否为对称二叉树,输入二叉树的根节点
bool helper(TreeNode *l,TreeNode *r){
if(l==NULL&&r==NULL) return true; //只有根节点的递归出口,判断为对称二叉树
if(l==NULL||r==NULL) return false;//最简单的非特殊情况,左右子树仅有一个返回false
if(l->val!=r->val) return false; //值不相同一定不是对称二叉树
return boolValue;
}
bool isSymmetric(TreeNode* root) {
if(root==NULL) return true; //没有根节点的空树,也判断为对称二叉树
return helper(root->left, root->right);
}
3、如何判断左子树和右子树对不对称?此时主要考虑用递归的非特殊情况,即左子树的左孩子和右子树的右孩子对称,左子树的右孩子和右子树的左孩子对称都满足时,左子树和右子树对称,这里大胆使用“递归的点”
//定义树节点
struct TreeNode{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int a){data=a;left=NULL;right=NULL;};
};
//判断是否为对称二叉树,输入二叉树的根节点
bool helper(TreeNode *l,TreeNode *r){
if(l==NULL&&r==NULL) return true; //只有根节点的递归出口,判断为对称二叉树
if(l==NULL||r==NULL) return false;//最简单的非特殊情况,左右子树仅有一个返回false
if(l->val!=r->val) return false; //值不相同一定不是对称二叉树
bool result_1=helper(l->left,r->right);//左子树的左孩子和右子树的右孩子是否对称
bool result_2=helper(l->right,r->left);//左子树的右孩子和右子树的左孩子是否对称
if(result_1&&result_2){
return true;
}else{
return false;
}
}
bool isSymmetric(TreeNode* root) {
if(root==NULL) return true; //没有根节点的空树,也判断为对称二叉树
return helper(root->left, root->right);
}
实现完毕!
总结: