​LeetCode解法汇总2192. 有向无环图中一个节点的所有祖先

 目录链接:

力扣编程题-解法汇总_分享+记录-CSDN博客

GitHub同步刷题项目:

https://github.com/September26/java-algorithms

原题链接:. - 力扣(LeetCode)


描述:

给你一个正整数 n ,它表示一个 有向无环图 中节点的数目,节点编号为 0 到 n - 1 (包括两者)。

给你一个二维整数数组 edges ,其中 edges[i] = [fromi, toi] 表示图中一条从 fromi 到 toi 的单向边。

请你返回一个数组 answer,其中 answer[i]是第 i 个节点的所有 祖先 ,这些祖先节点 升序 排序。

如果 u 通过一系列边,能够到达 v ,那么我们称节点 u 是节点 v 的 祖先 节点。

示例 1:

输入:n = 8, edgeList = [[0,3],[0,4],[1,3],[2,4],[2,7],[3,5],[3,6],[3,7],[4,6]]
输出:[[],[],[],[0,1],[0,2],[0,1,3],[0,1,2,3,4],[0,1,2,3]]
解释:
上图为输入所对应的图。
- 节点 0 ,1 和 2 没有任何祖先。
- 节点 3 有 2 个祖先 0 和 1 。
- 节点 4 有 2 个祖先 0 和 2 。
- 节点 5 有 3 个祖先 0 ,1 和 3 。
- 节点 6 有 5 个祖先 0 ,1 ,2 ,3 和 4 。
- 节点 7 有 4 个祖先 0 ,1 ,2 和 3 。

示例 2:

输入:n = 5, edgeList = [[0,1],[0,2],[0,3],[0,4],[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
输出:[[],[0],[0,1],[0,1,2],[0,1,2,3]]
解释:
上图为输入所对应的图。
- 节点 0 没有任何祖先。
- 节点 1 有 1 个祖先 0 。
- 节点 2 有 2 个祖先 0 和 1 。
- 节点 3 有 3 个祖先 0 ,1 和 2 。
- 节点 4 有 4 个祖先 0 ,1 ,2 和 3 。

提示:

  • 1 <= n <= 1000
  • 0 <= edges.length <= min(2000, n * (n - 1) / 2)
  • edges[i].length == 2
  • 0 <= fromi, toi <= n - 1
  • fromi != toi
  • 图中不会有重边。
  • 图是 有向 且 无环 的。

解题思路:

我们轻松的梳理出第i个节点依赖哪些节点,本题的难点就是如何按照正确的依赖顺序进行遍历。所以我们可以使用贪心策略,把满足依赖条件的加入到队列中。队列中取出来的就加入到最终的输出集合中。取出的节点如果满足了所有依赖条件,则也加入到队列中。

代码:

class Solution {
    public List<List<Integer>> getAncestors(int n, int[][] edges) {
        Model2192[] array = new Model2192[n];
        for (int i = 0; i < n; i++) {
            array[i] = new Model2192(i);
        }
        for (int i = 0; i < edges.length; i++) {
            int from = edges[i][0];
            int to = edges[i][1];
            array[from].toList.add(to);
            array[to].fromSet.add(from);
            array[to].dependSet.add(from);

        }
        List<Integer>[] out = new ArrayList[n];
        Queue<Model2192> queue = new ArrayDeque<>();
        for (int i = 0; i < n; i++) {
            if (array[i].fromSet.size() > 0) {
                continue;
            }
            queue.add(array[i]);
        }
        while (!queue.isEmpty()) {
            Model2192 top = queue.poll();
            addToList(out, top);
            actionTop(array, queue, top);
        }
        List<List<Integer>> outList = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            outList.add(out[i]);
        }
        return outList;
    }

    private void actionTop(Model2192[] array, Queue<Model2192> queue, Model2192 poll) {
        for (int to : poll.toList) {
            array[to].dependSet.remove(poll.value);
            array[to].fromSet.addAll(poll.fromSet);
            if (array[to].dependSet.size() == 0) {
                queue.add(array[to]);
            }
        }
    }

    private void addToList(List<Integer>[] out, Model2192 poll) {
        List<Integer> list = new ArrayList<>();
        out[poll.value] = list;
        list.addAll(poll.fromSet);
        Collections.sort(list);
    }


    static class Model2192 {
        int value = 0;
        List<Integer> toList = new ArrayList<>();
        Set<Integer> fromSet = new HashSet<>();
        Set<Integer> dependSet = new HashSet<>();

        Model2192(int _value) {
            this.value = _value;
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失落夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值