一、题目描述
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.
Input: [1,1]
Output: true
Possible partition: [1,1]
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 (牌的点数的上限)
二、题解
(1) 暴力枚举
枚举所有可能可能符合条件的 X(即每个组合的牌数), 根据题意得: N%X==0(N为卡牌数),假设有 C_i 张写有数字i的牌,每组数字为 i 的卡则有 X 张,那么一定会有 C_i % X == 0
/**
* 执行用时 3 ms 击败了 78.22% 的java用户
* 内存消耗 39.2MB 击败了 91% 的java用户
* @param deck
* @return
*/
public boolean hasGroupsSizeX(int[] deck) {
int[] count = new int[10000]; // 因为牌的点数最大为10000,所有要记录该点出现的次数就需要最大下标10000
for(int n : deck) {
count[n]++;
}
int N = deck.length;
LinkedList<Integer> valList = new LinkedList<>();
for(int n : count) {
if(n > 0) valList.addLast(n);
}
outFor: for (int X = 2; X <= N; X++) {
if(N % X == 0) {
for (int val : valList) {
if(val % X != 0)
continue outFor;
}
return true;
}
}
return false;
}
复杂度分析
-
时间复杂度:O(N^2 log logN),其中 NN 是卡片个数。本文不证明找到所有 NN 的因数个数的上界是 O(N log log N)。
-
空间复杂度:O(N)。
(2) 最大公约数
/**
* 最大公约数,假设 数字 i 有C_i张牌,其中没堆卡牌有 X 张,那么 X 一定可以整除 C_i,
* 求出count[i]的最大公约数是否 >= 2就可以得知,是否可按条件分组。
* 比如deck == {1,1,1,2,2,2,3,3},最大公约数是1。不满足条件
* deck{1,1,2,2,3,3}的gcd==2,则满足
*
* 执行用时 2 ms 击败了 99.56 % 的java用户
* 内存消耗 38.8MB 击败了 91.2% 的java用户
* @param deck
* @return
*/
public boolean hasGroupsSizeX2(int[] deck) {
int[] count = new int[10000];
for(int n : deck)
count[n]++;
int g = -1;
for (int i = 0; i < count.length; i++) {
if(count[i] > 0) {
if(g == -1)
g = count[i];
else
g = gcd(g, count[i]);
}
}
return g >= 2;
}
private int gcd(int x, int y) {
return x == 0 ? y : gcd(y%x, x);
}
复杂度分析
- 时间复杂度:O(N log^2 N)
N),其中 N 是卡片的个数。假设数字 i 有 Ci 张,那么每次 gcd 操作的复杂度是 O(log^2 C_i),存在更优的上界,但不在本文的考虑范围内。 - 空间复杂度:O(N)