LeetCode每日一题,20250910
[LeetCode 1733] 需要教语言的最少人数(Java 题解)
📝 题目描述
给定
n
种语言,每个用户会一些语言。如果两个人至少有一种共同的语言,就可以相互交流。
给定用户掌握的语言列表,以及好友关系列表,问:为了让所有好友都能互相交流,最少需要教会多少人 一门新语言?
👉 题目链接
🔍 思路分析
这道题的关键是不要一开始就想着教所有人语言,而是先把那些已经能交流的好友对排除掉,只针对不能交流的好友对考虑。
Step1. 快速判断两人能不能交流
- 建立一个二维数组
arr[i][k]
表示第i
个人是否会第k
种语言。 - 这样我们就能用
O(1)
时间判断某个人是否会某种语言。
Step2. 筛选出不能交流的好友对
- 遍历
friendships
数组。 - 如果两个好友
a, b
没有共同语言,就把(a, b)
加入“待解决列表”todoList
。
这里用到了 Java 的 label + continue 语法:
next:
for (var x : friendships) {int a = x[0] - 1, b = x[1] - 1;for (var y : languages[a]) {if (arr[b][y]) continue next; // 如果能交流,直接跳过这对好友}todoList.add(x); // 否则加入待解决列表
}
Step3. 枚举每一种语言,看看如果统一教这一种语言,最少要教多少人
-
对于待解决的每一对好友
(a, b)
:- 如果
a
不会这门语言,就要教a
。 - 如果
b
不会这门语言,就要教b
。
- 如果
-
用一个
Set<Integer>
来存这些人,避免重复计数。
最后取所有语言中人数最少的方案即可。
✅ Java 实现
import java.util.HashSet;
import java.util.Set;public class Solution {public int minimumTeachings(int n, int[][] languages, int[][] friendships) {int m = languages.length; // 学生人数boolean[][] arr = new boolean[m][n + 1];// 建立语言掌握表for (int i = 0; i < m; i++) {for (var x : languages[i]) {arr[i][x] = true;}}// 筛选出不能交流的好友对Set<int[]> todoList = new HashSet<>();next:for (var x : friendships) {int a = x[0] - 1, b = x[1] - 1;for (var y : languages[a]) {if (arr[b][y]) continue next; // 有共同语言,跳过}todoList.add(x);}// 枚举每一种语言int res = Integer.MAX_VALUE;for (int k = 1; k <= n; k++) {Set<Integer> set = new HashSet<>();for (var x : todoList) {int a = x[0] - 1, b = x[1] - 1;if (!arr[a][k]) set.add(a);if (!arr[b][k]) set.add(b);}res = Math.min(res, set.size());}return res;}
}
🎯 复杂度分析
- 建立语言表:
O(m * n)
- 筛选好友对:
O(friendships * 平均语言数)
- 枚举语言:
O(n * friendships)
总体来说效率完全可以接受。
💡 总结
这道题的关键点:
- 不要一开始就考虑所有人,而是只关注不能交流的好友对。
- 用二维数组快速判断是否会语言。
- 枚举所有语言,统计需要教的人数,取最小值。