夯实算法-25.卡牌分组

169 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

题目:LeetCode

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

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

示例 1:

输入: deck = [1,2,3,4,4,3,2,1]
输出: true
解释: 可行的分组是 [1,1][2,2][3,3][4,4]

示例 2:

输入: deck = [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 <= 10410^4
  • 0 <= deck[i] < 10410^4

解题思路

  • 若元素≤2 直接返回false\
  • 若计数中有个值为1,则不能完成分组,直接返回false\
  • 根据示例5,4个2被分成两组,就知道应该要求数组中数字个数的最大公约数,根据最大公约数进行分组,本题通过递归方式求得最大公约数。

代码实现

public boolean hasGroupsSizeX(int[] deck) {
    int[] counts=new int[10000]; 
    
    for(int i:deck) {
        counts[i]++; //计数
    }
    //获取所有元素的最大公约数,若最大公约数为1,则返回false
    int num=0;
    for(int i:counts) {
        //大于0表示有这个数
        if(i>0) {
            //得到最大公约数
            num=gcd(num,i);
            if(num == 1) return false;
        }
    }
    return num >= 2;
}
// 递归方式来求取最大公约数
private int gcd(int a,int b) {
    return b==0?a:gcd(b,a%b);
}

运行结果

Snipaste_2022-10-01_22-15-52.png

复杂度分析

  • 时间复杂度:O(NlogC)O(NlogC) 其中N是卡牌的个数,C是数值的范围,这里是10410^4
  • 空间复杂度:O(n)O(n)

掘金(JUEJIN)  一起分享知识, Keep Learning!