207. 课程表
超时解法:
class Solution {
bool dfs(vector<vector<int>>& graph, int i, vector<int> courses){
for(int j = 0; j < courses.size(); j++){
if(courses[j] == i)return false;
}
courses.emplace_back(i);
for(int j = 0; j < graph.size(); j++){
if(graph[i][j]){
if(!dfs(graph, j, courses))return false;
}
}
return true;
}
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
if(prerequisites.size() == 0)return true;
vector<vector<int>> graph(numCourses, vector<int>(numCourses));
for(int i = 0; i < prerequisites.size(); i++){
int a = prerequisites[i][0], b = prerequisites[i][1];
graph[a][b] = 1;
}
vector<int> courses;
for(int i = 0; i < numCourses; i++){
if(!dfs(graph, i, courses))return false;
}
return true;
}
};
优化了一下,使用 n u m C o u r c e s numCources numCources维的cources来标记当前是否遍历到,使用tranverse标记历史是否遍历到这门课,若遍历到下一次不需要再遍历。过了上次的超时用例,但是又来了新的超时用例。
class Solution {
bool dfs(vector<vector<int>>& graph, int i, vector<int>& courses, vector<int>& traverse){
if(courses[i] == 1)return false;
traverse[i] = 1;
for(int j = 0; j < graph.size(); j++){
if(graph[i][j]){
courses[i] = 1;
if(traverse[i] == 1 && courses[i] == 0)continue;
if(!dfs(graph, j, courses, traverse))return false;
courses[i] = 0;
}
}
return true;
}
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
if(prerequisites.size() == 0)return true;
vector<vector<int>> graph(numCourses, vector<int>(numCourses));
for(int i = 0; i < prerequisites.size(); i++){
int a = prerequisites[i][0], b = prerequisites[i][1];
graph[a][b] = 1;
}
vector<int> traverse(numCourses);
for(int i = 0; i < numCourses; i++){
if(traverse[i] == 0){
vector<int> courses(numCourses);
if(!dfs(graph, i, courses, traverse))return false;
}
}
return true;
}
};
/*
5
[[0,2],[2,1],[3,1],[1,4],[4,1]]
*/
参考题解,只是用一个数组来标记不同状态,只需要将其置为不同的值即可,比如用1表示当前遍历过的,用2表示已经遍历成功的课。
正确解法:
class Solution {
bool dfs(vector<vector<int>>& graph, int i, vector<int>& traverse){
traverse[i] = 1;
for(int j = 0; j < graph.size(); j++){
if(graph[i][j]){
if(traverse[j] == 1){
return false;
}
if(traverse[j] == 0){
if(!dfs(graph, j, traverse))return false;
}
}
}
traverse[i] = 2;
return true;
}
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
if(prerequisites.size() == 0)return true;
vector<vector<int>> graph(numCourses, vector<int>(numCourses));
for(int i = 0; i < prerequisites.size(); i++){
int a = prerequisites[i][0], b = prerequisites[i][1];
graph[a][b] = 1;
}
vector<int> traverse(numCourses);
for(int i = 0; i < numCourses; i++){
if(traverse[i] == 0){
if(!dfs(graph, i, traverse))return false;
}
}
return true;
}
};
结果:
还是很慢,可以不使用邻接矩阵,将graph[i]向量存储课程i的先修课程序列。
310. 最小高度树
注意,树的高度是所有子树高度的最大值+1.
又是超时!
超时代码:
class Solution {
vector<vector<int>> graph;
int min_len = 999999;
int getLevel(int node, int parent, int len){
if(len > min_len)return len;
if(graph[node].size() == 1 && graph[node][0] == parent){
return len;
}
int now_len = 0;
for(int i = 0; i < graph[node].size(); i++){
if(graph[node][i] != parent){
now_len = max(now_len, getLevel(graph[node][i], node, len + 1));
}
}
return now_len;
}
public:
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
vector<int> res;
if(n == 1){
res.push_back(0);
return res;
}
graph.resize(n);
for(int i = 0; i < edges.size(); i++){
graph[edges[i][0]].push_back(edges[i][1]);
graph[edges[i][1]].push_back(edges[i][0]);
}
for(int i = 0; i < n; i++){
int len = getLevel(i, -1, 1);
if(len < min_len){
min_len = len;
res.clear();
res.push_back(i);
}
else if(len == min_len)res.push_back(i);
}
return res;
}
};
看了下题解,果然最优思路不是暴力来做的,再优化还是很慢。
从图的边缘开始缩小图,每次将度为1的节点删除。使用队列来做,最后的队列就是答案。
正确解法:
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
vector<int> res;
if(n == 1){
res.push_back(0);
return res;
}
vector<vector<int>> graph(n);
vector<int> du(n);
for(int i = 0; i < edges.size(); i++){
graph[edges[i][0]].push_back(edges[i][1]);
graph[edges[i][1]].push_back(edges[i][0]);
du[edges[i][0]]++;
du[edges[i][1]]++;
}
queue<int> que;
for(int i = 0; i < n; i++){
if(du[i] <= 1)que.push(i);
}
while(que.size() != n){
int size = que.size();
n -= size;
while(size--){
int q = que.front();
que.pop();
for(int i = 0; i < graph[q].size(); i++){
int j = graph[q][i];
du[j]--;
if(du[j] == 1){
que.push(j);
}
}
}
}
for(int i = 0; i < n; i++){
res.push_back(que.front());
que.pop();
}
return res;
}
};
结果:
399. 除法求值
使用unordered_map来完成字符串到索引的映射,注意要使用 t r a n v e r s e tranverse tranverse来标记某节点是否被遍历过,或遍历过则说明程序跳进了循环,直接返回false。
递归解法:
class Solution {
bool dfs(vector<vector<pair<int, double>>>& graph, int x, int goal, int parent, double& res, vector<int>& tranverse){
if(tranverse[x] == 1)return false;
if(x == goal){
return true;
}
tranverse[x] = 1;
for(int i = 0; i < graph[x].size(); i++){
int nxt = graph[x][i].first;
if(nxt == parent)continue;
res *= graph[x][i].second;
if(dfs(graph, nxt, goal, x, res, tranverse))return true;
res /= graph[x][i].second;
}
return false;
}
public:
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
unordered_map<string, int> m;
vector<double> result;
int num = 0;
for(int i = 0; i < equations.size(); i++){
if(m.find(equations[i][0]) == m.end()){
m[equations[i][0]] = num++;
}
if(m.find(equations[i][1]) == m.end()){
m[equations[i][1]] = num++;
}
}
vector<vector<pair<int, double>>> graph(num);
for(int i = 0; i < equations.size(); i++){
int a = m[equations[i][0]], b = m[equations[i][1]];
if(a == b)continue;
graph[a].push_back(make_pair(b, values[i]));
graph[b].push_back(make_pair(a, 1 / values[i]));
}
/*for(auto it = m.begin(); it != m.end(); it++){
cout << it->first << " " << it->second << endl;
}
for(int i = 0; i < graph.size(); i++){
cout << "----------" << i << endl;
for(int j = 0; j < graph[i].size(); j++){
cout << graph[i][j].first << " " << graph[i][j].second << endl;
}
}*/
for(int i = 0; i < queries.size(); i++){
if(m.find(queries[i][0]) == m.end() || m.find(queries[i][1]) == m.end()){
result.push_back(-1.0);
continue;
}
int a = m[queries[i][0]], b = m[queries[i][1]];
double res = 1.0;
// cout << "cal " << a << " " << b << endl;
vector<int> tranverse(num);
if(dfs(graph, a, b, -1, res, tranverse)){
result.push_back(res);
}
else{
result.push_back(-1.0);
}
// cout << "res " << res << endl;
}
return result;
}
};
结果:
使用队列来完成非递归算法,其中使用数组 t e m p temp temp来存储中间值,初始化为-1.0。当遍历到节点i时,若 t e m p [ i ] ! = − 1.0 temp[i]!=-1.0 temp[i]!=−1.0时,则说明该节点被遍历过,因此直接跳过。
非递归解法:
class Solution {
public:
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
unordered_map<string, int> m;
vector<double> result;
int num = 0;
for(int i = 0; i < equations.size(); i++){
if(m.find(equations[i][0]) == m.end()){
m[equations[i][0]] = num++;
}
if(m.find(equations[i][1]) == m.end()){
m[equations[i][1]] = num++;
}
}
vector<vector<pair<int, double>>> graph(num);
for(int i = 0; i < equations.size(); i++){
int a = m[equations[i][0]], b = m[equations[i][1]];
if(a == b)continue;
graph[a].push_back(make_pair(b, values[i]));
graph[b].push_back(make_pair(a, 1 / values[i]));
}
/*for(auto it = m.begin(); it != m.end(); it++){
cout << it->first << " " << it->second << endl;
}
for(int i = 0; i < graph.size(); i++){
cout << "----------" << i << endl;
for(int j = 0; j < graph[i].size(); j++){
cout << graph[i][j].first << " " << graph[i][j].second << endl;
}
}*/
for(int i = 0; i < queries.size(); i++){
if(m.find(queries[i][0]) == m.end() || m.find(queries[i][1]) == m.end()){
result.push_back(-1.0);
continue;
}
int a = m[queries[i][0]], b = m[queries[i][1]];
double res = 1.0;
queue<int> que;
que.push(a);
vector<double> temp(num, -1.0);
temp[a] = 1.0;
while(temp[b] == -1.0 && !que.empty()){
int x = que.front();
que.pop();
for(int j = 0; j < graph[x].size(); j++){
int k = graph[x][j].first;
if(temp[k] == -1.0){
que.push(k);
temp[k] = temp[x] * graph[x][j].second;
}
}
}
result.push_back(temp[b]);
}
return result;
}
};
结果: