1. 程式人生 > 其它 >leedcode周賽 需要交語言的最少人數(兩種寫法)

leedcode周賽 需要交語言的最少人數(兩種寫法)

技術標籤:LeetCode

在一個由 m 個使用者組成的社交網路裡,我們獲取到一些使用者之間的好友關係。兩個使用者之間可以相互溝通的條件是他們都掌握同一門語言。

給你一個整數 n ,陣列 languages 和陣列 friendships ,它們的含義如下:

總共有 n 種語言,編號從 1 到 n 。
languages[i] 是第 i 位使用者掌握的語言集合。
friendships[i] = [u​​​​​​i​​​, v​​​​​​i] 表示 u​​​​​​​​​​​i​​​​​ 和 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 <= u​​​​​​i < v​​​​​​i <= languages.length 1 <= friendships.length <= 500 所有的好友關係 (u​​​​​i, v​​​​​​i) 都是唯一的。 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;

    }
};