tags:
- 简单
- 参考
- 数组
- 数学
flag: green
style: summer
date: ‘2019-7-11’
914.卡牌分组
一、题目
给定一副牌,每张牌上都写着一个整数。
此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组:
每组都有 X 张牌。
组内所有的牌上都写着相同的整数。
仅当你可选的 X >= 2 时返回 true。
-
示例 1:
输入:[1,2,3,4,4,3,2,1]
输出:true
解释:可行的分组是 [1,1],[2,2],[3,3],[4,4] -
示例 2:
输入:[1,1,1,2,2,2,3,3]
输出:false
解释:没有满足要求的分组。 -
示例 3:
输入:[1]
输出:false
解释:没有满足要求的分组。 -
示例 4:
输入:[1,1]
输出:true
解释:可行的分组是 [1,1] -
示例 5:
输入:[1,1,2,2,2,2]
输出:true
解释:可行的分组是 [1,1],[2,2],[2,2]
提示:
1 <= deck.length <= 10000
0 <= deck[i] < 10000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、解答
整体思路:最大公约数
- 解法一
class Solution {
public boolean hasGroupsSizeX(int[] deck) {
if (deck.length<=1){
return false;
}
if (deck.length==2){
return deck[0]==deck[1];
}
int max = Integer.MIN_VALUE;
for (int i=0;i<deck.length;i++){
max = max<deck[i] ? deck[i] : max;
}
int[] ints = new int[max+1];
Arrays.fill(ints,0);
max = Integer.MAX_VALUE;
for (int i=0;i<deck.length;i++){
ints[deck[i]]++;
}
for (int i=0;i<ints.length;i++){
if (ints[i] == 0){
continue;
}
if (ints[i] == 1){
return false;
}
max = max<ints[i]?max:ints[i];
}
for (int i=0;i<ints.length;i++){
if (ints[i] == 0){
continue;
}
if (ints[i]%max!=0){
int b = ints[i];
int a = max;
while(b!=0)
{
int r=a%b;
a=b;
b=r;
}
if (a>=2){
continue;
}
return false;
}
}
return true;
}
}
执行用时 :2 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗 :39 MB, 在所有 Java 提交中击败了91.28%的用户
- 解法二:
class Solution {
public boolean hasGroupsSizeX(int[] deck) {
if(deck == null || deck.length<=1) return false;
//sort the array
Arrays.sort(deck);
//calculate the number of every digit
int current = 1;
int count = 1;
int preRest = -1;
for(int i=1; i<deck.length; i++) {
if(deck[i] == deck[i-1]) count++;
else {
if(preRest == -1) preRest = count;
else preRest = getRest(count, preRest);
if(preRest < 2) return false;
count = 1;
current = deck[i];
}
}
if(preRest == -1) return count>=2;
else return getRest(preRest, count) >= 2;
}
private int getRest(int x, int y) {
if(y == 0) {
return x;
}
return getRest(y, x%y);
}
}
执行用时 :6 ms, 在所有 Java 提交中击败了94.40%的用户
内存消耗 :46.5 MB, 在所有 Java 提交中击败了73.85%的用户
- 解法 三;
利用数组下标法找元素,利用TreeSet去重排序,然后找所有相同的个数是否有最小公约数
class Solution {
public static boolean hasGroupsSizeX(int[] deck) {
if (deck == null || deck.length == 0) return false;
HashMap<Integer, Integer> hashMap = new HashMap<>();
for (int i : deck) {
hashMap.put(i, hashMap.getOrDefault(i, 0) + 1);
}
List<Integer> list = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : hashMap.entrySet()) {
list.add(entry.getValue());
}
Collections.sort(list);
int min = list.get(0);
boolean isX = false;
for (int i = 2; i <= min; i++) {
for (Integer j : list) {
if (j % i != 0) {
isX = false;
break;
}
isX = true;
}
if (isX) return true;
}
return false;
}
}
执行用时 :26 ms, 在所有 Java 提交中击败了54.06%的用户
内存消耗 :47.5 MB, 在所有 Java 提交中击败了66.06%的用户