拓扑排序_面试题

基本知识

  在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点。
  先统计所有节点的入度,对于入度为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;
	}
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值