一个图中连通三元组的最小度数
难度:
标签:
题目描述
给你一个无向图,整数 n
表示图中节点的数目,edges
数组表示图中的边,其中 edges[i] = [ui, vi]
,表示 ui
和 vi
之间有一条无向边。
一个 连通三元组 指的是 三个 节点组成的集合且这三个点之间 两两 有边。
连通三元组的度数 是所有满足此条件的边的数目:一个顶点在这个三元组内,而另一个顶点不在这个三元组内。
请你返回所有连通三元组中度数的 最小值 ,如果图中没有连通三元组,那么返回 -1
。
示例 1:

输入:n = 6, edges = [[1,2],[1,3],[3,2],[4,1],[5,2],[3,6]] 输出:3 解释:只有一个三元组 [1,2,3] 。构成度数的边在上图中已被加粗。
示例 2:

输入:n = 7, edges = [[1,3],[4,1],[4,3],[2,5],[5,6],[6,7],[7,5],[2,6]] 输出:0 解释:有 3 个三元组: 1) [1,4,3],度数为 0 。 2) [2,5,6],度数为 2 。 3) [5,6,7],度数为 2 。
提示:
2 <= n <= 400
edges[i].length == 2
1 <= edges.length <= n * (n-1) / 2
1 <= ui, vi <= n
ui != vi
- 图中没有重复的边。
代码结果
运行时间: 88 ms, 内存: 30.6 MB
/*
* 思路:
* 1. 使用邻接矩阵表示图,graph[i][j] == true 表示节点 i 和节点 j 之间有一条边。
* 2. 枚举每一个可能的三元组 (i, j, k),检查它们是否两两之间有边。
* 3. 对于每个有效的三元组,计算其度数。
* 4. 返回所有三元组的度数的最小值。
*/
import java.util.*;
import java.util.stream.IntStream;
public class Solution {
public int minTrioDegree(int n, int[][] edges) {
boolean[][] graph = new boolean[n + 1][n + 1];
int[] degree = new int[n + 1];
Arrays.stream(edges).forEach(edge -> {
graph[edge[0]][edge[1]] = true;
graph[edge[1]][edge[0]] = true;
degree[edge[0]]++;
degree[edge[1]]++;
});
int minDegree = IntStream.range(1, n + 1)
.flatMap(i -> IntStream.range(i + 1, n + 1)
.filter(j -> graph[i][j])
.flatMap(j -> IntStream.range(j + 1, n + 1)
.filter(k -> graph[i][k] && graph[j][k])
.map(k -> degree[i] + degree[j] + degree[k] - 6)))
.min()
.orElse(Integer.MAX_VALUE);
return minDegree == Integer.MAX_VALUE ? -1 : minDegree;
}
}
解释
方法:
此题解采用的是一种基于邻接表的方法来查找图中所有的连通三元组,并计算它们的度数。首先,使用一个哈希表 `maps` 来存储每个节点的邻接节点。对于每个节点 `i`,如果它的邻接节点少于两个,则无法形成三元组,跳过这样的节点。对于其他节点,首先对它们的邻接节点按照邻接节点数进行排序,以便优先处理可能形成连通三元组的节点组合。使用一种类似于广度优先搜索的方法来穷举所有可能的三元组组合,一旦找到一个有效的三元组,即计算其度数并更新最小度数。如果在遍历过程中发现存在度数更小的三元组,则更新结果 `res`。最终,如果没有找到任何连通三元组,返回 -1,否则返回最小的度数。
时间复杂度:
O(n^3)
空间复杂度:
O(E + n^2)
代码细节讲解
🦆
如何保证从邻接表中找到的三元组实际上是连通的?即如何验证三个节点两两之间都有边连接?
▷🦆
在算法中使用的BFS搜索方法具体是如何实现的?题解中提到使用队列q和访问集合v,能否详细解释这部分的逻辑和作用?
▷🦆
为什么在更新最小度数时,需要从各节点的度数总和中减去6?这里的6代表了什么具体的含义?
▷🦆
题解中提到如果节点的邻接节点少于两个就跳过该节点,这个判断的依据是什么?
▷