1. 程式人生 > >給定一棵二叉樹,和一個數值。求二叉樹的路徑和等於給定值的所有路徑

給定一棵二叉樹,和一個數值。求二叉樹的路徑和等於給定值的所有路徑

判斷是否有路徑

   bool hasPathSum(TreeNode *root, int sum) {
        if(root==NULL)
            return false;
        sum-=root->val;
        if(root->left==NULL&&root->right==NULL&&sum==0)
            return true;
        return hasPathSum(root->left,sum)||hasPathSum(root->right,sum);
    }

思路1 遍歷二叉樹,記錄所有葉子結點,然後依次向上遍歷到根節點。路徑和等於給定值,就說明符合;

    vector<vector<int> > pathSum(TreeNode *root, int sum) {
        vector<vector<int>> result;
        if(root==NULL)
            return result;
        unordered_map<TreeNode*,TreeNode*> mp;   //存放父子節點的關係
        vector<TreeNode*> leaf;                 //存放子節點
        queue<TreeNode*> que;  //按層遍歷
        que.push(root);
        mp[root]=root;
        while(!que.empty()){
            TreeNode* p=que.front();
            que.pop();
            if(p->left){
                mp[p->left]=p;
                que.push(p->left);
            }
            if(p->right){
                mp[p->right]=p;
                que.push(p->right);
            }
            if(p->left==NULL&&p->right==NULL)
                leaf.push_back(p);
        }
        for(TreeNode* q:leaf){
            vector<int> path;
            int count=0;
            while(q!=root){
                count+=q->val;
                path.push_back(q->val);
                q=mp[q];
            }
            count+=q->val;
            path.push_back(q->val);
            if(count==sum){
               //reverse(path.begin(),path.end());
               result.push_back(path);
            }
        }
        return result;
    }
思路 2: 遞迴

從根節點開始往下遍歷,用給定值減去當前節點值,如果當前節點是葉子結點,切減去後值為0,就說明找到一條路徑。否則,遞迴左右子樹

    vector<vector<int> > pathSum(TreeNode *root, int sum) {
        vector<vector<int>> result;
        if(root==NULL)
            return result;
        vector<int> path;
        pathSumCore(root,sum,path,result);
        return result;
    }
    void pathSumCore(TreeNode* root,int sum,vector<int> path,vector<vector<int>>& result){   //path 的引數不能是引用,因為每次都要複製
        if(root==NULL)
            return;
        path.push_back(root->val);
        sum-=root->val;                                 //減去當前結點的值
        if(root->left==NULL&&root->right==NULL&&sum==0)
            result.push_back(path);
        pathSumCore(root->left,sum,path,result);
        pathSumCore(root->right,sum,path,result);
    }

path引數也可以遞迴。只用每次做完後把當前節點在彈出去,

     vector<vector<int> > pathSum(TreeNode *root, int sum) {
        vector<vector<int>> result;
        if(root==NULL)
            return result;
        vector<int> path;
        pathSumCore(root,sum,path,result);
        return result;
    }
    void pathSumCore(TreeNode* root,int sum,vector<int>& path,vector<vector<int>>& result){
        if(root==NULL)
            return;
        path.push_back(root->val);
        sum-=root->val;
        if(root->left==NULL&&root->right==NULL&&sum==0)
            result.push_back(path);
        pathSumCore(root->left,sum,path,result);
        pathSumCore(root->right,sum,path,result);
        path.pop_back();           //引用 做完後要彈出當前元素
    }