0626-2020-LEETCODE-拓扑排序

本文介绍了拓扑排序的概念,并通过329.矩阵中的最长路径和207.课程表这两个LeetCode问题,展示了如何使用拓扑排序解决实际问题。文章提供了经典做法,即找出入度为0的节点,建立邻接表并进行操作。此外,还讨论了339.矩阵中的最长递增路径问题,利用出度的值进行递归遍历。
摘要由CSDN通过智能技术生成

什么是拓扑排序?

把这样一个 有向无环图 变成 线性的排序 就叫 拓扑排序。
代码来源:
https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/solution/zhi-jie-tao-yong-tuo-bu-pai-xu-mo-ban-mei-you-ji-q/

329.矩阵中的最长路径

class Solution {
    public int longestIncreasingPath(int[][] matrix) {
        if (matrix==null||matrix.length==0){
            return 0;
        }        
        int[][] count = new int[matrix.length][matrix[0].length];
        int[][] direction = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
        //统计每个点的入度用count数组保存,因为是递增,所以如果在上下左右,每发现一个比当前点小的数,当前点入度+1
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                for (int[] d : direction) {
                    if (longestIncreasingPathVerify(matrix, i + d[0], j + d[1]) && matrix[i + d[0]][j + d[1]] < matrix[i][j]) {
                        count[i][j]++;
                    }
                }
            }
        }
        Deque<int[]> deque = new LinkedList<>();
        //count数组中所有入度为0的点加入队列
        for (int i = 0; i < count.length; i++) {
            for (int j = 0; j < count[i].length; j++) {
                if (count[i][j] == 0) {
                    deque.add(new int[]{i, j});
                }
            }
        }
        int ans = 0;
        while (!deque.isEmpty()) {
            ans++;
            //这个跟课程表I那个题不一样,需要一层一层的出列,而不是一个一个的出,因为课程表那个不关心队列长度
            for (int size = deque.size(); size > 0; size--) {
                int[] poll = deque.poll();
                for (int[] d : direction) {
                    if (longestIncreasingPathVerify(matrix, poll[0] + d[0], poll[1] + d[1]) && matrix[poll[0] + d[0]][poll[1] + d[1]] > matrix[poll[0]][poll[1]]) {
                        if (--count[poll[0] + d[0]][poll[1] + d[1]] == 0) {
                            deque.add(new int[]{poll[0] + d[0], poll[1] + d[1]});
                        }
                    }
                }
            }
        }
        return ans;
    }

    private boolean longestIncreasingPathVerify(int[][] matrix, int i, int j) {
        return i >= 0 && j >= 0 && i < matrix.length && j < matrix[i].length;
    }
}

207.课程表

经典做法:
找出入度为0的点,建立邻接表,入队再出队即可。
作者:jyd
链接:https://leetcode-cn.com/problems/course-schedule/solution/course-schedule-tuo-bu-pai-xu-bfsdfsliang-chong-fa/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        int[] indegrees = new int[numCourses];
        List<List<Integer>> adjacency = new ArrayList<>();
        Queue<Integer> queue = new LinkedList<>();
        for(int i = 0; i < numCourses; i++)
            adjacency.add(new ArrayList<>());
        // Get the indegree and adjacency of every course.
        for(int[] cp : prerequisites) {
            indegrees[cp[0]]++;
            adjacency.get(cp[1]).add(cp[0]);
        }
        // Get all the courses with the indegree of 0.
        for(int i = 0; i < numCourses; i++)
            if(indegrees[i] == 0) queue.add(i);
        // BFS TopSort.
        while(!queue.isEmpty()) {
            int pre = queue.poll();
            numCourses--;
            for(int cur : adjacency.get(pre))
                if(--indegrees[cur] == 0) queue.add(cur);
        }
        return numCourses == 0;
    }
}

329.矩阵中的最长递增路径(多方法dfs/dp/拓扑排序)

记录出度的值,也就是每个点周围有几个比他大的,对每个出度为0的点,进行4个方向的遍历,出度不断地减,不断的循环,每循环一次就height++,直到最后容器里没有度为0的值,也就是,最后的点都有比自己小的点。

// Topological Sort Based Solution
// An Alternative Solution
public class Solution {
    private static final int[][] dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    private int m, n;
    public int longestIncreasingPath(int[][] grid) {
        int m = grid.length;
        if (m == 0) return 0;
        int n = grid[0].length;
        // padding the matrix with zero as boundaries
        // assuming all positive integer, otherwise use INT_MIN as boundaries
        int[][] matrix = new int[m + 2][n + 2];
        for (int i = 0; i < m; ++i)
            System.arraycopy(grid[i], 0, matrix[i + 1], 1, n);

        // calculate outdegrees
        int[][] outdegree = new int[m + 2][n + 2];
        for (int i = 1; i <= m; ++i)
            for (int j = 1; j <= n; ++j)
                for (int[] d: dir)
                    if (matrix[i][j] < matrix[i + d[0]][j + d[1]])
                        outdegree[i][j]++;

        // find leaves who have zero out degree as the initial level
        n += 2;
        m += 2;
        List<int[]> leaves = new ArrayList<>();
        for (int i = 1; i < m - 1; ++i)
            for (int j = 1; j < n - 1; ++j)
                if (outdegree[i][j] == 0) leaves.add(new int[]{i, j});

        // remove leaves level by level in topological order
        int height = 0;
        while (!leaves.isEmpty()) {
            height++;
            List<int[]> newLeaves = new ArrayList<>();
            for (int[] node : leaves) {
                for (int[] d:dir) {
                    int x = node[0] + d[0], y = node[1] + d[1];
                    if (matrix[node[0]][node[1]] > matrix[x][y])
                        if (--outdegree[x][y] == 0)
                            newLeaves.add(new int[]{x, y});
                }
            }
            leaves = newLeaves;
        }
        return height;
    }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/solution/ju-zhen-zhong-de-zui-chang-di-zeng-lu-jing-by-leet/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值