Leetcode:914. 卡牌分组

1、题目描述

给定一副牌,每张牌上都写着一个整数。

此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组:

  • 每组都有 X 张牌。
  • 组内所有的牌上都写着相同的整数。
    仅当你可选的 X >= 2 时返回 true。

2、 思路

  • 题目文字和示例 3 和告诉我们:如果检测到某个组里元素只有 1 个,可以直接返回 false。
  • 示例 5 非常特殊,是一个很重要的示例,[2, 2, 2, 2] 硬是被拆成了 2 组,为的是与组 [1, 1] 的元素个数相等。这对应了题目「每组都有 X 张牌」 的要求。
  • 遍历一次,统计每个数值的个数,如果某个数值只有 1 个,直接返回 false;
  • 再看一下示例 5,想更一般化的情况,输入 [2, 2, 2, 2, 3, 3, 3, 3, 3, 3],其实也是符合题意的分组,2 有 44 个,3 有 66 个,相同的 2 和 3 都需要拆成 2 个一组,因此这里的 X = 2,很显然 22 是这两个组的元素个数的公约数。

3、过程

  • 得到传入数组的所有个数,如果个数为1,则直接返回false
int len = deck.length;
if (len < 2) {
   
    return false;
}
  • 开始计数,求出每个数出现的次数,并用数组来标记即可。
int[] cnt = new int[10000];
for (int num : deck) {
   
     cnt[num]++;
 }
  • 利用变量接收下第一个数出现的次数,然后遍历整个计数的数组,如果这个数组里面有一个数为1,直接返回false,如果不为1,那就传入gcd函数中。
int x = cnt[deck[0]];

for (int i = 0; i < 10000; i++) {
   
     if (cnt[i] == 1) {
   
         return false;
     }
     if (cnt[i] > 1) {
   
         x = gcd(x, cnt[i]);
         // 这里做判断可以提前终止运行,也可以等到最后再做,各有优劣,任选其一
         if (x == 1) {
   
             return false;
         }
     }
 }
  • 书写gcd(int a, int b)函数,其实这个函数的作用就是求出公约数,并返回公约数。
private int gcd(int a, int b) {
   
     if (b == 0) {
   
         return a;
     }
     return gcd(b, a % b);
 }

具体代码如下:


/** * 给定一副牌,每张牌上都写着一个整数。 * * 此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组: * * 每组都有 X 张牌。 * 组内所有的牌上都写着相同的整数。 * 仅当你可选的 X >= 2 时返回 true。 */
public class p914 {
   

    /** * * @param deck 给定一副牌数组 * @return 仅当你可选的 X >= 2 时返回 true。 */

    public boolean hasGroupsSizeX1(int[] deck) {
   
        int len = deck.length;
        if (len < 2) {
   
            return false;
        }

        // 计数数组,10000 是根据题目给出的数值范围定的
        int[] cnt = new int[10000];
        for (int num : deck) {
   
            cnt[num]++;
        }

        // 先得到第 1 个数的个数,以避免在循环中赋值
        int x = cnt[deck[0]];

        for (int i = 0; i < 10000; i++) {
   
            if (cnt[i] == 1) {
   
                return false;
            }

            if (cnt[i] > 1) {
   
                x = gcd(x, cnt[i]);

                // 这里做判断可以提前终止运行,也可以等到最后再做,各有优劣,任选其一
                if (x == 1) {
   
                    return false;
                }
            }
        }
        return true;
    }



    private int gcd(int a, int b) {
   
        if (b == 0) {
   
            return a;
        }
        return gcd(b, a % b);
    }
    
    public static void main(String[] args) {
   
        int[] deck = new int[]{
   1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3};
        p914 test = new p914();
        System.out.println(test.hasGroupsSizeX1(deck));
    }
}