Contests

From Contest103 to Contest 104 ~

Contest104

914-M

914. X of a Kind in a Deck of Cards

In a deck of cards, each card has an integer written on it.

Return true if and only if you can choose X >= 2 such that it is possible to split the entire deck into 1 or more groups of cards, where:

Each group has exactly X cards. All the cards in each group have the same integer.

Example 1: Input: [1,2,3,4,4,3,2,1] Output: true Explanation: Possible partition [1,1],[2,2],[3,3],[4,4]

Example 2: Input: [1,1,1,2,2,2,3,3] Output: false Explanation: No possible partition.

Example 3: Input: [1] Output: false Explanation: No possible partition.

Example 4: Input: [1,1] Output: true Explanation: Possible partition [1,1]

Example 5: Input: [1,1,2,2,2,2] Output: true Explanation: Possible partition [1,1],[2,2],[2,2]

Note: 1 <= deck.length <= 10000 0 <= deck[i] < 10000

题目的意思是给一组数,把这组数分成若干小组,每小组包含的元素数目相同,至少为2,且组内的元素值相同。

Intuition:
比较直观,如何找到最好的那个K。
我们先统计这组数中每个数出现的频次,比如例2({1:3, 2:3, 3:2})(python可以利用Counter函数完成)。
因为分成的小组内的元素值相同,因此只能把同一个数分成若干组,且组内元素个数相同,这样我们需要考虑出现次数最少的数,它‘能’以及 需要分成多少组,假设出现次数最少的数的频次是min1,那么找一个刚好比它大的数,求二者的最大公约数res,这个公约数就是我们想要的K。

Code:

# 我的代码  
def hasGroupsSizeX(self, deck):
    def gcd(a, b):
        while b: a, b = b, a % b
        return a

    if len(deck) < 2: return False
    values = list(collections.Counter(deck).values())
    values.sort()

    mina, maxa = values[0], values[-1]
    if mina == maxa: return True

    for i in range(1, len(values)):
        if values[i] != mina:
            maxa = values[i]
            break
    gg = gcd(mina, maxa)

    if gg < 2:
        return False
    for i in values:
        if i % gg:
            return False
    return True

# 大佬的代码
def hasGroupsSizeX(self, deck):
    def gcd(a, b):
        while b: a, b = b, a % b
        return a
    count = collections.Counter(deck).values()
    return reduce(gcd, count) > 1

916-M

916. Word Subsets

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 5: Input: A = [“amazon”,“apple”,“facebook”,“google”,“leetcode”], B = [“ec”,“oc”,“ceo”] Output: [“facebook”,“leetcode”]

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

题目的意思就是说找出A中所有的word A[i],它满足,B中每一个(所有)的word B[j]都是A[i]的子集。

Intuition:
B中所有的word都是A[i]的子集的话,整个B就满足,它里面所有word可以的整合成一个具有所有character以及每个wordcharacter出现的频次的哈希表,这个频次只记录最高频次,比如appbp,它们整合起来,就是{a:1, b:1, p:2}

这样我们就把B缩减为了一个哈希表,遍历A是在所难免的了。

这道题很锻炼collections.Counter()的运用。

def wordSubsets(self, A, B):
    uni = collections.Counter()
    for b in B:
        for c, n in collections.Counter(b).items():
            uni[c] = max(uni[c], n)
    res = []
    for a in A:
        count = collections.Counter(a)
        if all(count[c] >= uni[c] for c in uni):
            res.append(a)
    return res

Contest103

910-M

910. Smallest Range II

Given an array A of integers, for each integer A[i] we need to choose either x = -K or x = K, and add x to A[i] (only once). After this process, we have some array B. Return the smallest possible difference between the maximum value of B and the minimum value of B. Example 1: Input: A = [0,10], K = 2 Output: 6 Explanation: B = [2,8] Example 2: Input: A = [1,3,6], K = 3 Output: 3 Explanation: B = [4,6,3] Note: 1 <= A.length <= 10000 0 <= A[i] <= 10000 0 <= K <= 10000

参考lee215的解释

Intuition: For each integer A[i],
we may choose either x = -K or x = K.

If we add K to all B[i], the result won’t change.

It’s the same as:
For each integer A[i], we may choose either x = 0 or x = 2 * K.

Explanation: We sort the A first, and we choose to add x = 0 to all A[i].
Now we have res = A[n - 1] - A[0].
Starting from the smallest of A, we add 2 * K to A[i],
hoping this process will reduce the difference.

Update the new mx = max(mx, A[i] + 2 * K)
Update the new mn = min(A[i + 1], A[0] + 2 * K)
Update the res = min(res, mx - mn)

Time Complexity: O(NlogN), in both of the worst and the best cases.

Remark: 理解他的update操作很有意思。我想找一个数,它加上2*K之后比原来最大的数要大(意味着题目中,这个数加上K比原来最大的数减去K要大,那么此时它就是最大的;如果它加之后还没有最大的数减去K大,那原来最大的数还是最大的)。

 def smallestRangeII(self, A, K):
    A.sort()
    res = A[-1] - A[0]
    for i in range(len(A) - 1):
        big = max(A[-1], A[i] + 2 * K)
        small = min(A[i + 1], A[0] + 2 * K)
        res = min(res, big - small)
    return res