Leetcode_深度优先搜索相关_c++版

(1)113路径总和二–中等

此题权值有正有负,实现里面没有剪枝。

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。
在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    
    
public:
    //先序遍历计算路径和
    void preOrderTraverse(int targetSum, TreeNode* root, vector<vector<int>>& result, int sum, vector<int> path){
    
    
        if(root == NULL) return;

        sum += root->val;
        path.push_back(root->val);
        //cout<< root->val;
        //到了叶节点,如果路径和等于目标,则放入结果集合
        if (root ->left == NULL && root->right == NULL){
    
    
            //cout<<sum<<endl;
            if(sum == targetSum){
    
    
                result.push_back(path);
            }return;
        }
        //数值有正有负,不能剪枝
        //if(targetSum >=0 && sum > targetSum) return;
       
        //递归先序变量
        preOrderTraverse(targetSum, root->left, result, sum, path);
        preOrderTraverse(targetSum, root->right, result, sum, path);
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
    
    
        vector<vector<int>> result;
        //if(root == NULL   ) return result;
        vector<int> path;
        preOrderTraverse(targetSum, root, result, 0, path);
        return result;

    }
};

在这里插入图片描述

(2)207课程表–中等

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。

在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。

例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
在这里插入图片描述

法一:深度优先遍历,发现环

class Solution {
    
    

    typedef struct GraphNode{
    
    
        int val;
        vector<GraphNode* > Neighbors;
        int label;
    }GraphNode;
public:
    //判断是否存在环
    void judgeCircle(GraphNode* graph, vector<int>& visit,bool& circleMark){
    
    
        //指针为空,则返回
        if(!graph) return;
        //找到环了,返回
        if(!circleMark) return;
        //没有neighbor,返回
        if((graph->Neighbors).size() == 0) {
    
    
            //cout<< "visiting "<<graph->label<<endl;
            visit[graph->label] = 1;
            return;
        }
        for(int i=0; i< (graph->Neighbors).size(); i++){
    
    
            //如果neighbor未访问过
            if( visit[(graph->Neighbors)[i]->label] == -1){
    
    
                visit[(graph->Neighbors)[i]->label] = 0;//状态改为正在访问
                judgeCircle((graph->Neighbors)[i], visit, circleMark);
                visit[(graph->Neighbors)[i]->label] = 1;
            }
            //如果neighbor是正在访问的节点
            else if(visit[(graph->Neighbors)[i]->label] == 0){
    
    
                circleMark = false;
                return;
            }
            visit[(graph->Neighbors)[i]->label] = 1;
           // }
            
        }

    }

    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
    
    
        vector<GraphNode*> graph;
        vector<int> visit;//3种状态,-1为未访问,0为正在访问,1为访问完毕
        bool circleMark = true;
        for(int i = 0; i< numCourses; i++){
    
    
            GraphNode* p = new GraphNode;
            p->label = i;
            graph.push_back(p);
            visit.push_back(-1);
        }
        for(int i = 0; i< prerequisites.size(); i++){
    
    
            graph[prerequisites[i][0]]->label = prerequisites[i][0];
            //cout<<  graph[prerequisites[i][0]]->label<<endl;
            graph[prerequisites[i][0]]->Neighbors.push_back(graph[prerequisites[i][1]]) ;
        }

        for(int i = 0; i< graph.size(); i++){
    
    
            
            visit[graph[i]->label] = 0;
            //cout<< "1";
            judgeCircle(graph[i], visit, circleMark);
            visit[graph[i]->label] = 1;
            if(!circleMark) return false;
        }return true;
    }
};

在这里插入图片描述

法二:利用拓扑排序,遍历所有入度为0的点,看是否能遍历完所有的点

class Solution {
    
    

    typedef struct GraphNode{
    
    
        int val;
        vector<GraphNode* > Neighbors;
        int label;
    }GraphNode;
public:
    //利用拓扑排序
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
    
    
        //if(prerequisites.size() <= 1 || numCourses <= 1) return true;
        vector<GraphNode*> graph;
        vector<int> depth;
        queue<GraphNode*> visit;

        for(int i = 0; i<numCourses; i++){
    
    
        //初始化图和depth数组
            GraphNode* p = new GraphNode;
            p->label = i;
            graph.push_back(p);
            depth.push_back(0);
        }

        for(int i = 0; i< prerequisites.size(); i++){
    
    
        //例如【1,0】,则说明学1之前需要学完0,则0的入度不需要改变,1号点的入度需要加一
            graph[prerequisites[i][1]]->Neighbors.push_back(graph[prerequisites[i][0]]);
            depth[prerequisites[i][0]]++;
        }

        while(true){
    
    
        	//每次遍历所有的点,将入度为0的点加入到队列中,直到没有点可加入为止
            for(int i = 0; i< numCourses; i++){
    
    
                if(depth[i]==0){
    
    
                    visit.push(graph[i]);
                }
            }

            if(visit.size() == 0) {
    
    
                break;
            }

            while(visit.size()){
    
    
            //访问队列中的每一个节点,将他们的邻居入度减一
                for(int i = 0; i< visit.front()->Neighbors.size(); i++){
    
    
                    depth[visit.front()->Neighbors[i]->label] --;
                }
                //已经访问过的节点depth置为-1
                depth[visit.front()->label] = -1;
                visit.pop();
                
            }

        }

        for(int i = 0; i< numCourses; i++){
    
    
        		//如果还有未访问的点则说明存在环
                if(depth[i]>0){
    
    
                   return false;
                }
        }
        return true;
       
    }
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44343355/article/details/132892442