Leetcode:914. 卡牌分组

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));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值