演算法學習記錄十三(C++)--->10年微軟面試題樹的子結構

Deft_MKJing宓珂璟發表於2017-08-31

描述

輸入兩棵二叉樹A和B,判斷樹B是不是A的子結構。

分析

例如,下圖中的兩棵樹A和B,由於A中有一部分子樹的結構和B是一樣的,因此B就是A的子結構。
這裡寫圖片描述

第一步:找到相同根節點
第二步:找到相同根節點後匹配左右子樹是否值都匹配

程式碼 (複雜flag版本但是思路很清晰)

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
/*
class Solution {
public:
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        bool flag = false;
        // 當兩棵樹都不為空的時候進行匹配
        if(!pRoot1 == NULL && !pRoot2 == NULL){
            if(pRoot1->val == pRoot2->val){
                // 當根節點相同的時候進行判斷是否包含
                flag = tree2ContainerTree1(pRoot1,pRoot2);
            }
            // 如果上面根節點不同,那麼flag是no  或者根節點相同而且對應的flag匹配失敗,還是no
            if(!flag){
                flag = HasSubtree(pRoot1->left,pRoot2);
            }
            // 如果左子樹未匹配到,那麼進行右子樹匹配
            if(!flag){
                flag = HasSubtree(pRoot1->right,pRoot2);
            }
        }
        return flag;
    }

    // 判斷是否被包含
    bool tree2ContainerTree1(TreeNode *node1, TreeNode *node2){
        // 當node2的樹遍歷完的時候就是被包含的
        if(node2 == NULL){
            return true;
        }
        // 當node1的樹提前結束,node2沒結束,肯定不包含
        if(node1 == NULL){
            return false;
        }
        // 當某個節點不同的時候 不包含
        if(node1->val != node2->val){
            return false;
        }
        // 如果根節點都對的上,那麼繼續用子節點進行匹配,左右都匹配到的時候才算被包含
        return tree2ContainerTree1(node1->left,node2->left) && tree2ContainerTree1(node1->right,node2->right);
    }
};
*/

程式碼(精簡版本)

class Solution {
public:
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(pRoot1 == NULL || pRoot2 == NULL)return false;
        return tree2ContainerTree1(pRoot1,pRoot2) ||
            HasSubtree(pRoot1->left,pRoot2) ||
            HasSubtree(pRoot1->right,pRoot2);
    }

    // 判斷是否被包含
    bool tree2ContainerTree1(TreeNode *node1, TreeNode *node2){
        if(node2 == NULL) return true;
        if(node1 == NULL) return false;
        if(node1->val == node2->val){
            return tree2ContainerTree1(node1->left,node2->left) && tree2ContainerTree1(node1->right,node2->right);
        }else{
            return false;
        }
    }
};


1.真的|| 運算子,C的特性就是當某一個為真的時候就不會繼續向下執行,因此不會有過多的運算
2.tree2ContainerTree1 該方法是當根節點一致的時候,左右子樹是否一致,當node2為空的時候 就是被包含了,如果node1提前為空,而node2還不為空,肯定不包含了,遞迴向左右進行節點判斷
3.HasSubtree 當根節點一致的時候,就去呼叫tree2ContainerTree1 進行包含判斷,但是如果不等,遞迴HasSubtree 進行匹配,直到節點相同進行包含判斷,否則的話就是不包含

相關文章