题目地址:卡牌地址
求得数组中每个数字出现的次数,然后求最大公约数,如果大于等于2,则返回true,否则false。
由于怎么求最大公约数忘了,查了一下:
class Solution {
public boolean hasGroupsSizeX(int[] deck) {
int[] chs = new int[10000];
//计数,将每个数字出现的次数记录下来
for (int no : deck) {
chs[no]++;
}
//迭代求多个数的最大公约数
int res = 0;
for (int cnt : chs) {
if (cnt > 0) { //只要这个数字有出现就求其公约数
res = gcd(res,cnt);
if(res==1) //某步gcd结果为1,说明某个数字只出现了一次,直接返回false
return false;
}
}
return res>=2;
}
//求最大公约数,用的是辗转相除
public int gcd(int x,int y){
return y==0 ? x : gcd(y,x%y);
}
}
结果:
官方还给了一种暴力破解:
class Solution {
public boolean hasGroupsSizeX(int[] deck) {
int N = deck.length;
int[] count = new int[10000];
//首先计数,记录每个数字出现的次数
for(int c:deck)
count[c]++;
List<Integer> values = new ArrayList<>();
//values中都是数字的个数
for (int i = 0; i < 10000; i++) {
if(count[i]>0)
values.add(count[i]);
}
search:
for (int X = 2; X <= N; X++) {
//枚举X是否是数组长度的约数
if(N%X==0){
for(int v:values)
//遍历每个数字个数是否是X的约数,如果有一个不是直接进入下一个X
if (v%X!=0)
continue search;
return true;
}
}
return false;
}
}
结果:
可以通过,在时间上不如第一种。