LeetCode 1857. Largest Color Value in a Directed Graph【拓扑排序,动态规划】困难

这篇具有很好参考价值的文章主要介绍了LeetCode 1857. Largest Color Value in a Directed Graph【拓扑排序,动态规划】困难。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。

为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库:https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。

由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。

给你一个 有向图 ,它含有 n 个节点和 m 条边。节点编号从 0 到 n - 1 。

给你一个字符串 colors ,其中 colors[i] 是小写英文字母,表示图中第 i 个节点的 颜色 (下标从 0 开始)。同时给你一个二维数组 edges ,其中 edges[j] = [aj, bj] 表示从节点 aj 到节点 bj 有一条 有向边 。

图中一条有效 路径 是一个点序列 x1 -> x2 -> x3 -> ... -> xk ,对于所有 1 <= i < k ,从 xi 到 xi+1 在图中有一条有向边。路径的 颜色值 是路径中 出现次数最多 颜色的节点数目。

请你返回给定图中有效路径里面的 最大颜色值  如果图中含有环,请返回 -1 。

示例 1:
LeetCode 1857. Largest Color Value in a Directed Graph【拓扑排序,动态规划】困难,# 拓扑排序,动态规划,leetcode,动态规划,算法

输入:colors = "abaca", edges = [[0,1],[0,2],[2,3],[3,4]]
输出:3
解释:路径 0 -> 2 -> 3 -> 4 含有 3 个颜色为 "a" 的节点(上图中的红色节点)。

示例 2:
LeetCode 1857. Largest Color Value in a Directed Graph【拓扑排序,动态规划】困难,# 拓扑排序,动态规划,leetcode,动态规划,算法

输入:colors = "a", edges = [[0,0]]
输出:-1
解释:从 00 有一个环。

提示:

  • n == colors.length
  • m == edges.length
  • 1 <= n <= 10^5
  • 0 <= m <= 10^5
  • colors 只含有小写英文字母。
  • 0 <= aj, bj < n

解法 拓扑排序 + 动态规划

我们需要求出的答案等价于:对于一种颜色 c c c ,以及一条路径 path \textit{path} path ,其中颜色为 c c c 的节点有 path c \textit{path}_c pathc。我们希望挑选 c c c 以及 p a t h path path ,使得 path c \textit{path}_c pathc 的值最大。

我们可以枚举颜色 c c c ,随后选出可以使得 path c \textit{path}_c pathc 达到最大值的 path \textit{path} path 。这些 path c \textit{path}_c pathc 中的最大值即为答案。

  • 如果给定的有向图包含环,那么它不存在拓扑排序。
  • 如果给定的有向图不包含环,那么这个有向图是一个「有向无环图」,它一定存在拓扑排序。
    根据拓扑排序的性质,如果节点 a a a 有一条有向边指向节点 b b b ,那么 b b b 在拓扑排序中一定出现在 a a a 之后。因此,一条有效路径上点的顺序与它们在拓扑排序中出现的顺序是一致的

我们可以根据拓扑排序来进行动态规划。设 d p [ v ] [ c ] dp[v][c] dp[v][c] 表示以节点 v v v 为终点的所有有效路径中,包含颜色 c c c 的节点数量的最大值。在进行状态转移时,我们考虑所有 v v v 的前驱节点(即有一条有向边指向 v v v 的节点) prev v \textit{prev}_v prevv
d p [ v ] [ c ] = ( max ⁡ u ∈ prev j d p [ u ] [ c ] ) + I ( v , c ) dp[v] [c] = \left( \max_{u \in \textit{prev}_j} dp [u][c] \right) + \mathbb{I}(v, c) dp[v][c]=(uprevjmaxdp[u][c])+I(v,c)
即找出前驱节点中包含颜色 c c c 的节点数量最多的那个节点进行转移,并且如果 v v v 本身的颜色为 c c c d p [ v ] [ c ] dp[v][c] dp[v][c] 的值就增加 1 1 1 。这里 I ( v , c ) \mathbb{I}(v, c) I(v,c) 为示性函数,当节点 v v v 的颜色为 c c c 时,函数值为 1 1 1 ,否则为 0 0 0 。那么 path c \textit{path}_c pathc 的最大值即为 d p [ v ] [ c ] dp[v][ c] dp[v][c] 中的最大值。

我们可以将状态转移,融入使用广度优先搜索的方法求解拓扑排序的过程中。当遍历到节点 u u u 时:

  • 如果 u u u 的颜色为 c c c ,那么将 d p [ u ] [ c ] dp[u] [c] dp[u][c] 的值增加 1 1 1
  • 枚举 u u u 的所有后继节点(即从 u u u 出发经过一条有向边可以到达的节点),对于后继节点 v v v ,将 d p [ v ] [ c ] dp[v][c] dp[v][c] 更新为其与 d p [ u ] [ c ] dp[u][c] dp[u][c] 的较大值。

这样的操作与上文描述的状态转移方程是一致的。它的好处在于,如果使用广度优先搜索的方法求解拓扑排序,那么我们需要使用邻接表存储所有的有向边,而上文的动态规划是通过「枚举 v → v → v 枚举前驱节点 u u u 」进行状态转移的,这就需要我们额外存储所有边的反向边,才能通过 v v v 找到所有的前驱节点。如果我们通过「枚举 u → u \to u 枚举后继节点 v v v 」进行状态转移,这样就与拓扑排序存储的边保持一致了。

class Solution {
public:
    int largestPathValue(string colors, vector<vector<int>>& edges) {
        int n = colors.size();
        vector<int> g[n];
        vector<int> ind(n); // 节点的入度统计,用于找出拓扑排序中最开始的节点
        for (vector<int>& e : edges) {
            g[e[0]].push_back(e[1]);
            ++ind[e[1]];
        }
        vector<array<int, 26>> dp(n);
        int found = 0, ans = 0;
        queue<int> q;
        for (int i = 0; i < n; ++i) if (ind[i] == 0) q.push(i); 
        while (!q.empty()) {
            int u = q.front(); q.pop();
            ++found;
            ++dp[u][colors[u] - 'a']; // 节点u对应的颜色+1
            ans = max(ans, dp[u][colors[u] - 'a']);
            for (int v : g[u]) {
                for (int c = 0; c < 26; ++c)
                    dp[v][c] = max(dp[u][c], dp[v][c]);
                if (--ind[v] == 0) q.push(v);
            } 
        } 
        return found != n ? -1 : ans;
    }
};

复杂度分析:文章来源地址https://www.toymoban.com/news/detail-615588.html

  • 时间复杂度: O ( n + m ∣ Σ ∣ ) O(n+m |\Sigma |) O(n+m∣Σ∣),其中 ∣ Σ ∣ |\Sigma | ∣Σ∣ 表示颜色的数量,在本题中 ∣ Σ ∣ = 26 |\Sigma |=26 ∣Σ∣=26
    一般的拓扑排序需要的时间为 O ( n + m ) O(n+m) O(n+m)。而在本题中在拓扑排序的过程中加入了状态转移,由于一条有向边对应着 ∣ Σ ∣ |\Sigma | ∣Σ∣ 次状态转移,因此拓扑排序的时间复杂度实际为 O ( n + m ∣ Σ ∣ ) O(n + m|\Sigma|) O(n+m∣Σ∣)
  • 空间复杂度: O ( n ∣ Σ ∣ + m ) O(n|\Sigma| + m) O(n∣Σ∣+m) 。我们需要 O ( n ∣ Σ ∣ ) O(n |\Sigma|) O(n∣Σ∣) 的空间存储对应数量的状态;我们需要 O ( n + m ) O(n+m) O(n+m) 的空间存储邻接表;我们需要 O ( n ) O(n) O(n) 的队列空间进行拓扑排序。将它们相加,即可得到总时间复杂度为 O ( n ∣ Σ ∣ + m ) O(n |\Sigma| + m) O(n∣Σ∣+m)

到了这里,关于LeetCode 1857. Largest Color Value in a Directed Graph【拓扑排序,动态规划】困难的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • LeetCode报错解决 Char 5: error: non-void function does not return a value in all control paths

    在做LeetCode第268题\\\"丢失的数字\\\"的时候报了这个错误 原答案 答案修改为如下 正确。 分析:原答案使用IF语句时出错。原答案只有在if语句下才有返回值,尽管不会有其他情况,但严谨的编译器还是会报错,让你把其他情况都写清楚。 感谢这篇文章

    2024年02月03日
    浏览(42)
  • LeetCode 2441. Largest Positive Integer That Exists With Its Negative【哈希集合】简单

    本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,

    2024年02月05日
    浏览(38)
  • Could not resolve placeholder “xxx“ in value “${}“ springboot启动报错:IllegalArgumentException: Could not resolve placeholder ‘‘ in value “${}“

    在网上看了很多方法,都没有用。 首先我确定我的yml配置文件里面配置没有错: 然后地址引用的地方也加了@Value,类上也加了@Service注解,引用的格式也没有错   其次,我也试过了maven install,package,再三检查了target文件里面有配置文件, 发现都没有错 但是就是报错,经过

    2024年02月11日
    浏览(47)
  • 【LeetCode】210. 课程表 II——拓扑排序

    题目链接:210. 课程表 II 题目描述: 现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 1。给你一个数组 prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修 bi 。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示:[0,1] 。 返

    2024年02月09日
    浏览(34)
  • 【LeetCode: 210. 课程表 II:拓扑排序+图】

    🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,CSDN-Java领域优质创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文

    2024年02月09日
    浏览(58)
  • 算法沉淀——BFS 解决拓扑排序(leetcode真题剖析)

    Breadth-First Search (BFS) 在拓扑排序中的应用主要是用来解决有向无环图(DAG)的拓扑排序问题。拓扑排序是对有向图中所有节点的一种线性排序,使得对于每一条有向边 (u, v),节点 u 在排序中都出现在节点 v 的前面。如果图中存在环路,则无法进行拓扑排序。 BFS 解决拓扑排序

    2024年02月21日
    浏览(40)
  • Could not resolve placeholder “xxx“ in value “${}“

    在网上看了很多方法,都没有用。 首先我确定我的yml配置文件里面配置没有错: 然后地址引用的地方也加了@Value,类上也加了@Service注解,引用的格式也没有错   其次,我也试过了maven install,package,再三检查了target文件里面有配置文件, 发现都没有错 但是就是报错,经过

    2024年02月08日
    浏览(49)
  • Making Large Language Models Perform Better in Knowledge Graph Completion论文阅读

    原文链接: Making Large Language Models Perform Better in Knowledge Graph Completion 基于大语言模型(LLM)的知识图补全(KGC) 旨在利用 LLM 预测知识图谱中缺失的三元组 ,并丰富知识图谱,使其成为更好的网络基础设施,这可以使许多基于网络的自动化服务受益。然而,基于LLM的KGC研究有

    2024年01月23日
    浏览(47)
  • 论文阅读 Improved Appliance Classification in NILM Using Weighted RCNN (recurrence graph)

    Publisher: Energies Publising Date: 2020 MOTIVATION OF READING: 1. zero-crossing method for data preprocessing. 2.  recurrence graph (RG). Probelm statement:  the performance of V–I-based approaches is still unsatisfactory as it is still not distinctive enough to recognize devices that fall into the same category. Methodology:  an appliance recognition

    2024年01月22日
    浏览(30)
  • 前端页面报错(Cannot use ‘in‘ operator to search for ‘value‘ in undefined)

    问题示例:Cannot use \\\'in\\\' operator to search for \\\'username\\\' in {\\\"uid\\\":1,\\\"username\\\":\\\"admin\\\",\\\"password\\\":\\\"$2a$10$2zYH..Q3317nAJyQshN/iu9z.hzARVTblk3If42mWQMCNZIhFWaxm\\\",\\\"gender\\\":\\\"1\\\",\\\"image\\\":\\\"/\\\",\\\"telephone\\\":\\\"15039465258\\\",\\\"balance\\\":null,\\\"email\\\":\\\"\\\",\\\"isDeleted\\\":0,\\\"gmtCreate\\\":\\\"2022-12-13T01:23:54.000+0000\\\",\\\"gmtModified\\\":\\\"2022-12-13T01:24:01.000+0000\\\",\\\"code\\\":null

    2024年02月12日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包