(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;
}
};