基本知识
在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点。
先统计所有节点的入度,对于入度为0的节点就可以分离出来,然后把这个节点指向的节点的入度减一。一直做该操作,直到所有的节点都被分离出来。
如果最后不存在入度为0的节点,那就说明有环,不存在拓扑排序,因此,拓扑排序和深度优先搜索常被用来检测有向图是否有环路。
简单面试题
题目:你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 。在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]。
给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?
code:
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
//构造邻接表
vector<int> inDegrees(numCourses);
vector<int> v;
vector<vector<int>> tables(numCourses);
//用队列实现拓扑排序
for(int i = 0;i < numCourses;i++) {
inDegrees[i] = 0;
tables.push_back(v);
}
for(int i = 0;i < prerequisites.size();i++) {
inDegrees[prerequisites[i][0]]++; //入度++
tables[prerequisites[i][1]].push_back(prerequisites[i][0]);
}
//遍历inDegrees,找到入席为0的结点
queue<int> q;
for(int i = 0;i < inDegrees.size();i++)
if(inDegrees[i] == 0)
q.push(i);
int cnt = 0;
while(!q.empty()) {
int v = q.front();
q.pop();
cnt++;
//遍历从v出发的入度
for(int i = 0;i < tables[v].size();i++) {
inDegrees[tables[v][i]]--;
if(inDegrees[tables[v][i]] == 0)
q.push(tables[v][i]);
}
}
return numCourses == cnt;
}
};
通过这个面试题,能初识拓扑排序的基本结构。在拓扑排序中,有三个重要的信息要记录,分别为一个队列(对入度为0的顶点进行入队和出队),记录每个顶点入度数的数组和点与点连接关系的二维数组(或链表)。这些处理好,拓扑排序就成功了。
复杂面试题
矩阵中的最长递增路径
给定一个整数矩阵,找出最长递增路径的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
代码:
class Solution {
public:
int longestIncreasingPath(vector<vector<int>>& matrix) {
queue<int> qx, qy;
const int rows = matrix.size();
if (!rows)
return 0;
const int cols = matrix[0].size();
const vector<int> dx = { 1, -1, 0, 0 };
const vector<int> dy = { 0, 0, 1, -1 };
vector<vector<int>> in(rows, vector<int>(cols, 0));
vector<vector<int>> dp(rows, vector<int>(cols, 1));
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
for (int k = 0; k < 4; k++) {
int nx = i + dx[k];
int ny = j + dy[k];
if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && matrix[i][j] < matrix[nx][ny]) {
in[nx][ny]++;
}
}
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++) {
if (!in[i][j]) {
qx.push(i);
qy.push(j);
}
}
int ret = 0;
while (!qx.empty()) {
int i = qx.front();
int j = qy.front();
qx.pop();
qy.pop();
if (dp[i][j] > ret)
ret = dp[i][j];
int nv = dp[i][j] + 1;
for (int k = 0; k < 4; k++) {
int nx = i + dx[k];
int ny = j + dy[k];
if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && matrix[i][j] < matrix[nx][ny]) {
if (dp[nx][ny] < nv)
dp[nx][ny] = nv;
in[nx][ny]--;
if (!in[nx][ny]) {
qx.push(nx);
qy.push(ny);
}
}
}
}
return ret;
}
};