深度优先搜索DFS(二)

1,545 阅读3分钟

LeetCode 113. 路径总和 II

题目1.png 题意:给出一棵二叉树,给定一个目标数值targetSum,输出所有从根节点到叶子节点路径数值和与targetSum相等的路径。

思路:遍历所有路径,可以使用深度优先搜索,搜索完一条路径再到下一条路径;使用容器记录当前走的节点和容器内的数值和,当当前节点是叶子节点就判断容器内的数值和是否等于targetSum,如果是就存储容器内的节点。

例子:使用题目给出的数据,targetSum是22; 1-1.png 定义一个容器(存储路径)和一个整形(计算总和),从根节点开始遍历整棵二叉树,图下是完成了第一条路径,判断条件是子节点左右子节点是空,nSum跟targetSum不相等,这条路径不成立;

1-2.png 再进行下一条路径,返回上一节点之前需要将nSum减去当前节点和容器弹出对应节点。图下是第二条路径,nSum等于targetSum,路径成立,将容器内的数值存储下来;

1-3.png 进行下一条路径,流程也跟上述一样,最后到叶子节点,判断nSum与targetSum是否相等,不行等路径不成立;

1-4.png 进行下一条路径,nSum与targetSum相等,将容器内数值存储下来;

1-5.png 下一条路径,nSum与targetSum不行等;

1-6.png 搜索完毕。

1-7.png 主要流程如上述所示。 代码实现如下:

class Solution {
public:
    void DFS(TreeNode* root, vector< vector<int> >& res, 
              vector<int> tmpres, int targetSum, int& nSum) {
        if(root == nullptr) {
            return ;
        }
        nSum += root->val;
        tmpres.push_back(root->val);
        if(nSum == targetSum && root->left == nullptr && 
            root->right == nullptr) {
            res.push_back(tmpres);
            tmpres.pop_back();
            nSum -= root->val;
            return ;
        }
        DFS(root->left, res, tmpres, targetSum, nSum);
        DFS(root->right, res, tmpres, targetSum, nSum);
        nSum -= root->val;
        tmpres.pop_back();
    }

    vector< vector<int> > pathSum(TreeNode* root, 
                                    int targetSum) {
        vector< vector<int> > result;
        result.clear();
        vector<int> path;
        int nSum = 0;
        DFS(root, result, path, targetSum, nSum);
        return result;
    }
};

LeetCode 437. 路径总和 III

timu2.png 题意:这题跟上一题也是找路径nSum跟targetSum相等的路径,但是可以不从根节点开始和结束不用是叶子节点,不过路径是要连续向下的。

思路:跟上一题一样,先找出完整的一条路径,然后再进行路径的数值遍历,计算子路径和是否跟targetSum相等,如果到了另外一条完整路径,其中的子路径已经遍历过的话,我们就不进行计算,重复上述流程,直到遍历完整棵二叉树。

例子:使用题目给出的数据,targetSum是8;

2-1.png 定义一个容器(存储路径)、一个整形nSum(计算总和)、另一个整形nTag(已经遍历过路径的前n个子节点)。

图下为第一条遍历到的路径,当前节点左右子节点都是空,找到一条完整的路径,就进行子路径的遍历,计算出nSum,判断是否有targetSum相等的子路径; 2-2.png

2-3.png 下一条路径,然后nTag标记成3,因为前三个数已经是有遍历过的,不重复进行计算,计算剩下的子路径 2-4.png

2-5.png 下一条路径,nTag标记成2; 2-6.png

2-7.png 下一条路径,nTag标记成1; 2-8.png

2-9.png 搜索完毕,主要流程如上述所示。

代码实现如下:

class Solution {
public:
    void DFS(TreeNode* root, vector<int> path, int targetSum, 
              int& nResult, int& nTag){
        if(root == nullptr) {
            return ;
        }
        path.push_back(root->val);
        if(root->left == nullptr && root->right == nullptr) {
            for(int i=0; i<path.size(); i++) {
                int nSum = 0;
                for(int j=i; j<nTag; j++) {
                    nSum += path[j];
                }
                int k = nTag;
                if(i > nTag) k = i;
                for(int j=k; j<path.size(); j++) {
                    nSum += path[j];
                    if(nSum == targetSum) {
                        nResult++;
                    }
                }
            }
            nTag = path.size();
            path.pop_back();
            nTag--;
            return ;
        }
        if(root->left != nullptr) {
            DFS(root->left, path, targetSum, nResult, nTag);
        }
        if(root->right != nullptr) {
            DFS(root->right, path, targetSum, nResult, nTag);
        }
        path.pop_back();
        nTag--;
    }

    int pathSum(TreeNode* root, int targetSum) {
        int nResult = 0;
        vector<int> path;
        int nTag = 0;
        DFS(root, path, targetSum, nResult, nTag);
        return nResult;
    }
};