【字符串】B039_LC_收藏清單(暴力 / set 優化 / 邏輯優化)

一、Problem

Given the array favoriteCompanies where favoriteCompanies[i] is the list of favorites companies for the ith person (indexed from 0).

Return the indices of people whose list of favorite companies is not a subset of any other list of favorites companies. You must return the indices in increasing order.

Input: favoriteCompanies = [["leetcode","google","facebook"],["google","microsoft"],["google","facebook"],["google"],["amazon"]]
Output: [0,1,4] 
Explanation: 
Person with index=2 has favoriteCompanies[2]=["google","facebook"] which is a subset of favoriteCompanies[0]=["leetcode","google","facebook"] corresponding to the person with index 0. 
Person with index=3 has favoriteCompanies[3]=["google"] which is a subset of favoriteCompanies[0]=["leetcode","google","facebook"] and favoriteCompanies[1]=["google","microsoft"]. 
Other lists of favorite companies are not a subset of another list, therefore, the answer is [0,1,4].

Constraints:

1 <= favoriteCompanies.length <= 100
1 <= favoriteCompanies[i].length <= 500
1 <= favoriteCompanies[i][j].length <= 20
All strings in favoriteCompanies[i] are distinct.
All lists of favorite companies are distinct, that is, If we sort alphabetically each list then favoriteCompanies[i] != favoriteCompanies[j].
All strings consist of lowercase English letters only.

二、Solution

方法一:暴力(超時)

  • 先記錄每一個用戶的 id 到數組 id 中,然後按照用戶的收藏數進行降序排列。
  • 因爲降序排列後,收藏數多的列表一定不是收藏數少的列表的子集。
  • 按收藏數從少到多枚舉用戶的收藏列表是否爲收藏數多的列表的子集。

很不幸,54/55 超時了

class Solution {
    public List<Integer> peopleIndexes(List<List<String>> fav) {
        ArrayList<Integer> res = new ArrayList<>();
        int tot = 0;
        Integer[] id = new Integer[fav.size()];
        for (int i = 0; i < fav.size(); i++) {
           id[tot++] = i;
        }
        Arrays.sort(id, (e1, e2) -> fav.get(e2).size() - fav.get(e1).size());
        for (int i = tot-1; i >= 0; i--) {
            boolean f = true;
            for (int j = i-1; j >= 0; j--) {
                if (fav.get(id[j]).containsAll(fav.get(id[i]))) {
                    f = false;
                    break;
                }
            }
            if (f) res.add(id[i]);
        }
        Collections.sort(res);
        return res;
    }
}

複雜度分析

  • 時間複雜度:O(n2×m×len)O(n^2 × m × len),大概 10000×500×10000 × 500 × 1nleni\sum_{1}^{n} len_i,會超時
  • 空間複雜度:O(n)O(n)

方法二:優化

爲什麼方法一會超時?佛樂,用 set 根本不用對集合排序,

class Solution {
    public List<Integer> peopleIndexes(List<List<String>> fav) {
        ArrayList<Integer> res = new ArrayList<>();
        int n = fav.size();
        for (int i = 0; i < n; i++) {
            boolean f = true;
            List<String> a = fav.get(i);
            for (int j = 0; j < n; j++) {
                if (i == j)
                    continue;
                Set<String> b = new HashSet<>(fav.get(j));
                if (b.containsAll(a)) {
                    f = false;
                    break;
                }
            }
            if (f) res.add(i);
        }
        return res;
    }
}

複雜度分析

  • 時間複雜度:O(n3)O(n^3)
  • 空間複雜度:O(n)O(n)

參考了一位大神的思路,人家是對每一個人的收藏列表 fav[i] 的內部進行排序的,這樣做可以避免兩個清單的包含關係的比較用 O(n2)O(n^2) 的時間比較出來,比如,而是直接加速到 O(n)O(n)

list1:[a, b, c] => [a,b,c]
list2:[c, b] => 	[b, c]
那麼比較就可以用 O(n) 的時間得出兩個清單的包含關係
class Solution {
    public List<Integer> peopleIndexes(List<List<String>> fav) {
        List<Integer> res = new LinkedList<>();
        int n = fav.size();
        for (int i = 0; i < n; i++) 
            Collections.sort(fav.get(i));
        for (int i = 0; i < n; i++) {
            boolean fl = true;
            for (int j = 0; j < n; j++) {
                if (i == j) 
                	continue;
                List<String> a = fav.get(i), b = fav.get(j);
                int match = 0;
                for (int k = 0; k < b.size() && match < a.size(); k++) {
                    if (a.get(match).equals(b.get(k)))
                        match++;
                }
                if (match >= a.size()) {
                    fl = false;
                    break;
                }
            }
            if (fl) res.add(i);
        }
        return res;
    }
}

複雜度分析

  • 時間複雜度:O(nmk)O(nmk)
  • 空間複雜度:O(n)O(n )
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章