leedcode周賽 需要交語言的最少人數(兩種寫法)
阿新 • • 發佈:2021-01-25
技術標籤:LeetCode
在一個由 m 個使用者組成的社交網路裡,我們獲取到一些使用者之間的好友關係。兩個使用者之間可以相互溝通的條件是他們都掌握同一門語言。
給你一個整數 n ,陣列 languages 和陣列 friendships ,它們的含義如下:
總共有 n 種語言,編號從 1 到 n 。
languages[i] 是第 i 位使用者掌握的語言集合。
friendships[i] = [ui, vi] 表示 ui 和 vi 為好友關係。
你可以選擇 一門 語言並教會一些使用者,使得所有好友之間都可以相互溝通。請返回你 最少 需要教會多少名使用者。
請注意,好友關係沒有傳遞性,也就是說如果 x 和 y 是好友,且 y 和 z 是好友, x 和 z 不一定是好友。
示例 1:
輸入:n = 2, languages = [[1],[2],[1,2]],
friendships = [[1,2],[1,3],[2,3]]
輸出:1
解釋:你可以選擇教使用者 1 第二門語言,也可以選擇教使用者 2
第一門語言。
示例 2:
輸入:n = 3, languages = [[2],[1,3],[1,2],[3]], friendships = [[1,4],[1,2],[3,4],[2,3]]
輸出:2
解釋:教使用者 1 和使用者 3 第三門語言,需要教 2 名使用者。
提示:
2 <= n <= 500
languages.length == m
1 <= m <= 500
1 <= languages[i].length <= n
1 <= languages[i][j] <= n
1 <= ui < vi <= languages.length
1 <= friendships.length <= 500
所有的好友關係 (ui, vi) 都是唯一的。
languages[i] 中包含的值互不相同。
解題方法:
總體的思路就是將O (n^3)將到O(n^2)。
1.將每個人會什麼語言使用unordered_map<int,unordered_set<int>>
記錄下來,使用unordered_set可以使查詢時時間複雜度降到O(1)。
這步操作時間複雜度O(n^2)。
2.將朋友關係中原本就不能相互溝通的朋友對篩選出來。
時間複雜度O(n^2)。
3.遍歷每一門語言,再遍歷每一個不能溝通朋友對,判斷是否會當前語言,
不會則教會該人,人數加一,同時注意使用unordered_set集合記錄下
已經教會了哪些人。該步操作同樣只需要O(n^2)。
複雜度分析:
時間複雜度:O(n^2)
空間複雜度:O(n^2)
class Solution {
public:
int minimumTeachings(int n, vector<vector<int>>& languages, vector<vector<int>>& friendships) {
// 步驟1
unordered_map<int,unordered_set<int>> memo;
for (int i = 0;i < languages.size();++i){
for (int j = 0;j < languages[i].size();++j){
memo[i + 1].insert(languages[i][j]);
}
}
// 步驟2
vector<vector<int>> temp;
for (int i = 0;i < friendships.size();++i){
int a = friendships[i][0],b = friendships[i][1];
int flag = 0;
for (int j = 0;j < languages[a - 1].size();++j){
if (memo[b].count(languages[a - 1][j])){
flag = 1;
break;
}
}
if (flag == 0) temp.push_back({a,b});
}
if (temp.size() == 0) return 0;
// 步驟3
int ans = INT_MAX;
for (int i = 1;i <= n;++i){
unordered_set<int> st;
int count = 0;
for (int j = 0;j < temp.size();++j){
int a = temp[j][0],b = temp[j][1];
if (!memo[a].count(i) && !st.count(a)){
++count;
st.insert(a);
}
if (!memo[b].count(i) && !st.count(b)){
++count;
st.insert(b);
}
}
ans = min(ans,count);
}
return ans;
}
};
//貪心
class Solution {
public:
int minimumTeachings(int n, vector<vector<int>>& languages, vector<vector<int>>& friendships) {
int m = languages.size();
vector<vector<bool>> g(m + 1, vector<bool>(n + 1));
for (int i = 0; i < languages.size(); i ++ ) {
for (auto x: languages[i]) {
g[i + 1][x] = true;//使用者會這種語言就標記true
}
}
set<int> persons;
for (auto& f: friendships) {
int x = f[0], y = f[1];
bool flag = false;
for (int i = 1; i <= n; i ++ ) //遍歷所有語言
if (g[x][i] && g[y][i]) { //好友之間能交流
flag = true;
break;
}
if (flag) continue;
persons.insert(x), persons.insert(y);
}
int s = 0;
vector<int> cnt(n + 1);
for (auto x: persons) {
for (int i = 1; i <= n; i ++ )
if (g[x][i]) {
cnt[i] ++ ;
s = max(s, cnt[i]);
}
}
return persons.size() - s;
}
};