剑指offer--搜索与回溯算法(简单)


搜索与回溯算法(简单)

一、剑指 Offer 26. 树的子结构

代码如下(示例):

【C++代码】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSubStructure(TreeNode* A, TreeNode* B) {
        if(!A ||!B) return false;
        if(isPart(A,B)) return true;
        return isSubStructure(A->left,B)||isSubStructure(A->right,B);
    }

    bool isPart(TreeNode*p1,TreeNode *p2){
        if(!p2) return true;
        if(!p1||p1->val !=p2->val) return false;
        return isPart(p1->left,p2->left)&&isPart(p1->right,p2->right);
    }
};

【分析】
若树B是树A的子结构,则子结构的根节点可能为树A的任意一个节点。因此,判断树B是否是A的子结构,需要完成以下两步骤工作:

  1. 前序遍历树A中的每个节点nA;(对应于isSubStucture(A,B));
  2. 判断树A中以nA为根节点的子树是包含树B.(对应于函数isPart(A,B))

【算法流程】:
名词规定:树A的根节点记作节点A,树B的根节点称为节点B
isPart(A,B)函数

 bool isPart(TreeNode*p1,TreeNode *p2){
        if(!p2) return true;
        if(!p1||p1->val !=p2->val) return false;
        return isPart(p1->left,p2->left)&&isPart(p1->right,p2->right);
    }
 //1、终止条件:
 	//1、当节点B为空,说明树B已经匹配完成
 	//2、当节点A为空,说明已经越过树A叶子节点,即匹配失败,返回false
 	//3、当节点A和B的值不同:说明匹配失败,返回false
//2、返回值
	//1、判断A和B的左子节点是否相等,即isPart(p1->left,p2->left)
	//2、判断A和B的右子节点是否相等,即isPart(A->right,B->right);

isSubStructure(A,B)函数:

//1、	特例处理:当树A为空或树B为空时,直接返回false;
//2、	返回值:若树B是树A的子结构,则必须满足以下三种情况之一,因此用或连接
	//1、	以节点A为根节点的子树包含树B,对应isPart(A,B);
	//2、	树B是树A左子树的子结构,对应isSubStructure(A->left,B)
	//3、	树B是树A右子树的子结构,对应isSubStructure(A->right,B);
 bool isSubStructure(TreeNode* A, TreeNode* B) {
        if(!A ||!B) return false;
        if(isPart(A,B)) return true;
        return isSubStructure(A->left,B)||isSubStructure(A->right,B);
    }

二、剑指 Offer 27. 二叉树的镜像

【C++代码】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* mirrorTree(TreeNode* root) {
        if(!root) return nullptr;
        mirrorTree(root->left);
        mirrorTree(root->right);
        swap(root->left,root->right);
        return root;
    }
};

【分析】
在这里插入图片描述


三、剑指 Offer 28. 对称的二叉树

【C++代码】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        return dfs(root->left,root->right);
    }
    bool dfs(TreeNode*p,TreeNode*q){
        if(!p||!q) return !q&&!p;
        if(p->val !=q->val) return false;
        return dfs(p->left,q->right) &&dfs(p->right,q->left);
    }
};

[分析]
解题思路:
对称二叉树定义:对于树中任意两个对称节点L和R,一定有
1、L->val = R->val;即对称节点值相等
2、L->>left->val = r->right->val;即L的左子节点和R的右子节点对称;
3、L->right->val = R->left->val;即L的右子节点和R的左子节点对称。
根据以上规律,考虑从顶至底层递归,判断每对节点是否对称,从而判断树是否为对称二叉树。
在这里插入图片描述
【算法流程】:

/*isSymmetric(root):
特例处理:若根节点root为空,则直接返回true.
返回值:即dfs(root->left,root->right);

*/
 bool isSymmetric(TreeNode* root) {
        if(!root) return true;
        return dfs(root->left,root->right);
    }

/*dfs(left,right):
终止条件:
	当left和right同时越过叶节点:此树从顶至底的节点都对称,因此返回ture;
	当left和right中有一个越过叶节点:此树不对称
	当节点L值不等于节点R值:此树不对称
递推工作:
	判断两节点L->left和R->right是否对称,即dfs(L->left,R->right);
	判断两节点L->right和R->left是否对称,即dfs(L->right,R->left);
返回值 :两节点都对称时,才是对称树,因此用与逻辑&&连接
*/
bool dfs(TreeNode*p,TreeNode*q){
        if(!p||!q) return !q&&!p;
        if(p->val != q->val) return false;
        return dfs(p->left,q->right) &&dfs(p->right,q->left);
    }


版权声明:本文为weixin_43488529原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。