当前位置: 首页 > news >正文

力扣热题-有向图中最大颜色值

        本文介绍了力扣1857题"有向图中最大颜色值"的解法。题目要求在给定有向图中找出路径中出现次数最多的颜色值,若图中存在环则返回-1。主要解法采用拓扑排序检测环,并结合动态规划维护各节点26种颜色的最大出现次数。时间复杂度为O(n+m26),空间复杂度为O(n26+m)。Java和C++实现均通过拓扑排序处理节点,动态规划更新颜色状态,最终返回最大颜色值或检测到环时返回-1。该解法有效结合了图论算法和动态规划技巧来解决问题。

目录

题目链接:1857. 有向图中最大颜色值 - 力扣(LeetCode)

题目描述

解法一:图论中的环检测+动态规划的状态传递

Java写法:

C++写法:

运行时间

时间复杂度和空间复杂度

总结


题目链接:1857. 有向图中最大颜色值 - 力扣(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:

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

示例 2:

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

提示:

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

解法一:图论中的环检测+动态规划的状态传递

        这道题的解题思路需要结合图论中的环检测和动态规划的状态传递。首先得明确题目要找的是所有有效路径中颜色出现次数最多的那个值,同时还要处理图中可能存在环的情况。这里的关键在于如何高效地遍历可能的路径并统计颜色出现次数,同时避免陷入环的死循环。

        整个思路可以分成两部分来看。第一部分是判断图中是否存在环,这可以通过拓扑排序来解决。拓扑排序的原理是按节点入度逐步处理,如果最终处理过的节点数量不等于总节点数,说明存在环。这一步不仅是环检测的基础,也为后续的动态规划提供了处理顺序——因为拓扑排序保证了在处理每个节点时,所有可能到达它的前驱节点都已经被处理过。

        第二部分是动态规划维护颜色状态。每个节点需要记录以它为终点的所有路径中,各个颜色出现的最大次数。比如当前节点颜色是红色,那么它的红色计数需要在前驱节点红色计数的基础上加1,其他颜色则继承前驱中的最大值。这种设计巧妙地利用了路径的叠加性质——不同前驱带来的颜色分布会被动态比较,保留最大值继续向后传递。

        具体来说,当处理拓扑排序中的某个节点时,会先用它的颜色更新自己的计数,然后将这个状态传递给所有后继节点。每个后继节点会综合所有前驱传递来的状态,取各颜色的最大值作为自己的基准状态。这样层层传递下去,最终每个节点记录的颜色最大值实际上代表了以它为终点的所有路径中颜色分布的极限情况。

        整个过程像流水线上的装配,每个节点在拓扑顺序中被"激活"时,已经收集了所有可能影响它的路径信息。最后只需要遍历所有节点的颜色记录,就能找到全局最大值。如果中途发现环,直接返回-1,这相当于在流水线检测到故障时立即停机报错。

Java写法:

import java.util.*;class Solution {public int largestPathValue(String colors, int[][] edges) {int n = colors.length();List<List<Integer>> graph = new ArrayList<>();int[] indeg = new int[n];int[][] dp = new int[n][26]; // dp[i][c] 表示以节点i结尾的路径中颜色c的最大出现次数// 初始化邻接表for (int i = 0; i < n; i++) graph.add(new ArrayList<>());for (int[] e : edges) {graph.get(e[0]).add(e[1]);indeg[e[1]]++;}// 拓扑排序队列初始化Queue<Integer> q = new LinkedList<>();for (int i = 0; i < n; i++) {if (indeg[i] == 0) {q.offer(i);dp[i][colors.charAt(i) - 'a'] = 1; // 自身颜色初始化为1}}int processed = 0, max = 0;while (!q.isEmpty()) {int u = q.poll();processed++;int curMax = Arrays.stream(dp[u]).max().getAsInt();max = Math.max(max, curMax);for (int v : graph.get(u)) {for (int c = 0; c < 26; c++) {// 继承u的颜色计数,若当前节点颜色为c则+1int newVal = dp[u][c] + (colors.charAt(v) - 'a' == c ? 1 : 0);dp[v][c] = Math.max(dp[v][c], newVal);}indeg[v]--;if (indeg[v] == 0) q.offer(v);}}return processed == n ? max : -1; // 检测环}
}

C++写法:

#include <vector>
#include <queue>
#include <algorithm>
using namespace std;class Solution {
public:int largestPathValue(string colors, vector<vector<int>>& edges) {int n = colors.size();vector<vector<int>> graph(n);vector<int> indeg(n, 0);vector<vector<int>> dp(n, vector<int>(26, 0)); // dp[i][c] 记录颜色c的最大出现次数// 构建邻接表和入度数组for (auto& e : edges) {graph[e[0]].push_back(e[1]);indeg[e[1]]++;}queue<int> q;for (int i = 0; i < n; i++) {if (indeg[i] == 0) {q.push(i);dp[i][colors[i] - 'a'] = 1; // 初始化自身颜色}}int processed = 0, max_val = 0;while (!q.empty()) {int u = q.front();q.pop();processed++;int cur_max = *max_element(dp[u].begin(), dp[u].end());max_val = max(max_val, cur_max);for (int v : graph[u]) {for (int c = 0; c < 26; c++) {// 更新后继节点的颜色计数int new_val = dp[u][c] + (colors[v] - 'a' == c ? 1 : 0);dp[v][c] = max(dp[v][c], new_val);}indeg[v]--;if (indeg[v] == 0) q.push(v);}}return processed == n ? max_val : -1; // 环检测}
};

运行时间

时间复杂度和空间复杂度

        复杂度主要分两部分来看。拓扑排序处理环检测和节点遍历,这部分的时间是线性的,和节点数加边数成正比。因为每个节点和边各处理一次,所以时间复杂度是O(n + m)。动态规划维护颜色状态的部分,每条边在传递时要处理26种颜色,相当于每条边要乘上颜色种类的常数,所以整体的时间复杂度是O(n + m*26)。对于一般的问题规模,这个复杂度是可以接受的,特别是当边数不是特别大的时候。

        空间上,最大的开销来自记录每个节点的26种颜色出现次数的二维数组,这部分占用了O(n26)的空间。邻接表存储图结构需要O(n + m)的空间,入度数组和队列占用的空间相对较小。综合起来,空间复杂度是O(n26 + m)。这样的设计在空间利用上是比较紧凑的,没有浪费额外的内存,主要开销都花在了必要的数据结构上。



总结

        本文介绍了力扣1857题"有向图中最大颜色值"的解法。题目要求在给定有向图中找出路径中出现次数最多的颜色值,若图中存在环则返回-1。主要解法采用拓扑排序检测环,并结合动态规划维护各节点26种颜色的最大出现次数。时间复杂度为O(n+m26),空间复杂度为O(n26+m)。Java和C++实现均通过拓扑排序处理节点,动态规划更新颜色状态,最终返回最大颜色值或检测到环时返回-1。该解法有效结合了图论算法和动态规划技巧来解决问题。

相关文章:

  • Leetcode-4 数组异或操作
  • 深入解读Qwen3技术报告(六):Qwen3性能评估
  • 自动化测试工具:Selenium详解
  • Docker 使用镜像[SpringBoot之Docker实战系列] - 第537篇
  • 本地依赖库的版本和库依赖的版本不一致如何解决?
  • Rust 1.0 发布十周年,梦想再度扬帆起航!
  • 【杂谈】STM32使用快速傅里叶变换库函数后如何比较准确地找到n次谐波幅值
  • 【生物信息学】k-mer的基本概念及应用
  • 限制 SSH 访问仅允许特定 IP 连接
  • 【Python-Day 18】玩转函数参数:*args 与 **kwargs 终极指南
  • 华为OD机试真题——考勤信息(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现
  • 树莓派4B 在系统环境安装snap7 西门子plc通讯包(佟掌柜专用)
  • 高电流测量新突破:借助铜进行温度补偿
  • 2025端午北海游玩攻略
  • ROS2基础知识
  • Linux系统:动静态库的制作与安装
  • 【向量数据库选型实战】FAISS vs Chroma vs Milvus vs Qdrant 全面对比
  • MPI实现大数据Ring Broadcast逻辑
  • 如何做好一份技术文档:从精准导航到持续迭代的实践指南
  • MySQL的基础操作
  • 优秀网站主题/微信软文
  • 做网站要属于无形资产吗/如何免费注册一个网站
  • 网站建设注意细节问题/什么平台推广效果最好
  • 专业网站开发制作公司/怎么让网站快速收录
  • 开发公司通知未办理交房业主质保期到期的函件/刷seo快速排名
  • 东莞专业网站建设推广/黑河seo