BFS
- 仔细思考发现,他们除法运算的关系就是图的数据结构, a / b a / b a/b 就相当于与从 a a a 走到 b b b 的边权乘积,边权就是他们的倍数关系 v a l u e s values values 。
- 为了更高效的构造邻接表,使用哈希表,将变量对映射成整数,然后对于每个 q u e r y query query 只需 B F S BFS BFS 从起点走到终点即可。
class Solution {
public:
typedef pair<int,double> PID;
unordered_map<string,int> um;
double bfs(string &a, string &b, vector<vector<PID>> &edges) {
if(a == b) return 1;
int st = um[a], ed = um[b];
queue<int> que; que.emplace(st);
vector<double> dis(um.size(),-1);
dis[st] = 1;
while(que.size()) {
auto u = que.front(); que.pop();
for(auto &[v,val]: edges[u]) {
if(dis[v] == -1) {
dis[v] = dis[u] * val;
if(v == ed) return dis[v];
que.emplace(v);
}
}
}
return -1;
}
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
int idx = 0;
for(int i = 0; i < equations.size(); i++) { //将变量哈希成整数
if(!um.count(equations[i][0])) um[equations[i][0]] = idx++;
if(!um.count(equations[i][1])) um[equations[i][1]] = idx++;
}
vector<vector<PID>> edges(um.size());
for(int i = 0; i < equations.size(); i++) { //构造邻接表
auto &x = equations[i][0], &y = equations[i][1];
int u = um[x], v = um[y];
edges[u].emplace_back(v, values[i]);
edges[v].emplace_back(u, 1/values[i]); //反方向就是倒数
}
vector<double> res;
for(auto query: queries) {
auto &a = query[0], &b = query[1];
if(!um.count(a) || !um.count(b)) {
res.emplace_back(-1);
} else {
res.emplace_back(bfs(a,b,edges)); //bfs获得a到b路径上的乘积
}
}
return res;
}
};
记忆化搜索
比较简单就不赘述了。
class Solution {
public:
int ne[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};
int n, m;
int dfs(int x,int y, vector<vector<int>> &matrix, vector<vector<int>> &f) {
if(f[x][y]) return f[x][y];
f[x][y]++;
for(int i = 0; i < 4; i++) {
int tx = x + ne[i][0];
int ty = y + ne[i][1];
if(tx < 0 || tx >= n || ty < 0 || ty >= m) continue;
if(matrix[x][y] < matrix[tx][ty]) {
f[x][y] = max(f[x][y], dfs(tx,ty,matrix,f) + 1);
}
}
return f[x][y];
}
int longestIncreasingPath(vector<vector<int>>& matrix) {
n = matrix.size(), m = matrix[0].size();
vector<vector<int>> f(n, vector<int>(m,0));
int res = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
res = max(res, dfs(i,j,matrix,f));
return res;
}
};
拓扑排序(BFS)
将所有元素小的指向大的这就生成了有向图,然后拓扑排序一下,然后这里拓扑排序的层数就是答案,也就是最长的升序序列。
class Solution {
public:
static constexpr int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int rows, columns;
int longestIncreasingPath(vector< vector<int> > &matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) {
return 0;
}
rows = matrix.size();
columns = matrix[0].size();
auto outdegrees = vector< vector<int> > (rows, vector <int> (columns));
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
for (int k = 0; k < 4; ++k) {
int newRow = i + dirs[k][0], newColumn = j + dirs[k][1];
if (newRow >= 0 && newRow < rows && newColumn >= 0 && newColumn < columns && matrix[newRow][newColumn] > matrix[i][j]) {
++outdegrees[i][j];
}
}
}
}
queue < pair<int, int> > q;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
if (outdegrees[i][j] == 0) {
q.push({i, j});
}
}
}
int ans = 0;
while (!q.empty()) {
++ans;
int size = q.size();
for (int i = 0; i < size; ++i) {
auto cell = q.front(); q.pop();
int row = cell.first, column = cell.second;
for (int k = 0; k < 4; ++k) {
int newRow = row + dirs[k][0], newColumn = column + dirs[k][1];
if (newRow >= 0 && newRow < rows && newColumn >= 0 && newColumn < columns && matrix[newRow][newColumn] < matrix[row][column]) {
--outdegrees[newRow][newColumn];
if (outdegrees[newRow][newColumn] == 0) {
q.push({newRow, newColumn});
}
}
}
}
}
return ans;
}
};
简单的拓扑排序
- 首先构造课程的拓扑图,将所有需要先完成的课程指向想要学习的课程。
- 将所有入度为0的都加入队列中,然后 b f s bfs bfs 依次弹出所有的点,这个顺序就是答案了。
class Solution {
public:
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
int n = prerequisites.size();
vector<int> res;
if(n == 0) {
for(int i = 0; i < numCourses; i++) res.emplace_back(i);
return res;
}
vector<vector<int>> adj(numCourses);
vector<int> in(numCourses);
for(int i = 0; i < n; i++) {
int &u = prerequisites[i][1], &v = prerequisites[i][0];
adj[u].emplace_back(v);
in[v]++;
}
queue<int> que;
for(int i = 0; i < numCourses; i++)
if(in[i] == 0) que.emplace(i);
while(que.size()) {
int u = que.front(); que.pop();
res.emplace_back(u);
for(int v: adj[u]) {
in[v]--;
if(in[v] == 0) que.emplace(v);
}
}
return res.size() < numCourses? vector<int>{}: res;
}
};