Contests
From Contest103 to Contest 104 ~
Contest104
914-M
914. X of a Kind in a Deck of Cards
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
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
以及每个word
中character
出现的频次的哈希表,这个频次只记录最高频次,比如app
和bp
,它们整合起来,就是{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
参考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