题目

We are given two arrays A and B of words. Each word is a string of lowercase letters.

Now, say that word b is a subset of word a if every letter in b occurs in a, including multiplicity. For example, “wrr” is a subset of “warrior”, but is not a subset of “world”.

Now say a word a from A is universal if for every b in B, b is a subset of a.

Return a list of all universal words in A. You can return the words in any order.

Example 1:

Input: A = [“amazon”,”apple”,”facebook”,”google”,”leetcode”], B = [“e”,”o”] Output: [“facebook”,”google”,”leetcode”]

Example 2:

Input: A = [“amazon”,”apple”,”facebook”,”google”,”leetcode”], B = [“l”,”e”] Output: [“apple”,”google”,”leetcode”] Example 3:

Input: A = [“amazon”,”apple”,”facebook”,”google”,”leetcode”], B = [“e”,”oo”] Output: [“facebook”,”google”] Example 4:

Input: A = [“amazon”,”apple”,”facebook”,”google”,”leetcode”], B = [“lo”,”eo”] Output: [“google”,”leetcode”] Example 5:

Input: A = [“amazon”,”apple”,”facebook”,”google”,”leetcode”], B = [“ec”,”oc”,”ceo”] Output: [“facebook”,”leetcode”]

Note: 1 <= A.length, B.length <= 10000 1 <= A[i].length, B[i].length <= 10 A[i] and B[i] consist only of lowercase letters. All words in A[i] are unique: there isn’t i != j with A[i] == A[j].

分析

题目很简单,定义sub(A, B)为B中的字符能够完全在A中找到。也就是说:对于任意字符b属于B,num(A, b) > num(B, b)。 num(X, n)代表X字符串中含有n字符的个数。 给定两个字符串集合,要找到所有满足条件的a:1. a属于A;2. 对于任意b属于B,都有sub(a, b)为true。 算法的时间复杂度为O((NBb + a) * NA)即O(NBNAb),其中NB表示N集合中字符串个数,b代表平均每个字符串中字符的个数。空间复杂度为O(a/b)。 仔细观察可以发现:不一定需要每次都计算字符串A与字符串集合中每一个字符串的结果,我们可以将字符串集合B中所有的结果组合起来,取每个字符的最大值,只需要一个中间结果就能满足条件。时间复杂度为O(NBb + NAa),即O(NAa)。空间复杂度仍然为O(1)

答案

class Solution {
    public List<String> wordSubsets(String[] A, String[] B) {
        int[] totalB = new int[26];
        for (String b : B) {
            int[] wordCount = convertWord(b);
            for (int i = 0; i < 26; i++) {
                if (wordCount[i] > totalB[i]) {
                    totalB[i]  = wordCount[i];
                }
            }
        }
        
        List<String> result = new LinkedList<>();
        for (String a : A) {
            int[] wordCount = convertWord(a);
            if (sub(wordCount, totalB)) {
                result.add(a);
            }
        }
        return result;
    }
    
    private boolean sub(int[] wordA, int[] wordB) {
        for (int i = 0; i < wordB.length; i++) {
            if (wordA[i] < wordB[i]) {
                return false;
            }
        }
        return true;
    }
    
    private int[] convertWord(String string) {
        int[] count = new int[26];
        for (char ch : string.toCharArray()) {
            int index = ch - 'a';
            count[index] += 1;
        }
        return count;
    }
}

结果

Runtime: 17 ms, faster than 92.96% of Java online submissions for Word Subsets. Memory Usage: 49.9 MB, less than 73.77% of Java online submissions for Word Subsets.