leetcode 914. X of a Kind in a Deck of Cards
題目
一摞牌,每張牌上寫了一個整數,如果能找到一個大於等於2的數X,把牌分成1或多組滿足下列條件:
- 每組有X張牌
- 每組裡的每張牌上寫得數字都是一樣的
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]
注意:
- 1 <= deck.length <= 10000
- 0 <= deck[i] < 10000
思路
把牌按照上面寫的數字分組計數(counter),將counter排序,為了找到最小的兩個計數。如果最小的計數小於2,也就是牌堆只有一張牌,則不存在大於等於2的X,返回FALSE。如果counter只有一個值,也就是隻有一種數字的牌,通過了前面的條件這張牌的張數就不小於2,至少可以按照要求分成1組,返回True。接下來是複雜一點的地方,如果counter前兩個計數的最大公約數,是後續所有計數的一個約數,那麼就返回True,否則返回False。
程式碼
class Solution: def hasGroupsSizeX(self, deck): """ :type deck: List[int] :rtype: bool """ def biggest_divider(a, b): for i in range(2, min(a, b)+1): if a % i == 0 and b % i == 0: return i return False from collections import defaultdict counter = defaultdict(int) for i in deck: counter[i] += 1 values = sorted(list(counter.values())) if values[0] < 2: return False if len(values) == 1: return True bd = biggest_divider(values[0], values[1]) if not bd: return False for i in range(2, len(values)): if values[i] % bd !=0: return False return True
其他
討論裡面有個一行程式碼搞定的
return reduce(fractions.gcd, collections.Counter(deck).values()) > 1
很巧妙,我又學習了一下reduce,如果reduce的序列只有一個值,就返回這個值,不論reduce的函式是什麼。
這道題我試了好多次錯,沒想太明白,其中一次我的提交裡面把[1,1,1, 1,1,1, 1,1,1]判為False了,AC了,leetcode的測試用例沒覆蓋到。