Leetcode.914 卡牌分组

题目链接

Leetcode.914 卡牌分组 Rating : 1371

题目描述

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

此时,你需要选定一个数字 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
解释:没有满足要求的分组。

提示:
  • 1 < = d e c k . l e n g t h < = 1 0 4 1 <= deck.length <= 10^4 1<=deck.length<=104
  • 0 < = d e c k [ i ] < 1 0 4 0 <= deck[i] < 10^4 0<=deck[i]<104

解法:数论

一共有 n n n 张牌。需要将其分为若干组,组内每张牌都相同,并且每一组有 X 张牌。

很显然 X 是 n n n 的约数,即 X % n = 0 X \% n = 0 X%n=0

假设给定的 n n n 张牌,共有 k k k 种牌, ( c n t 1 , c n t 2 , c n t 3 , . . . , c n t k − 1 , c n t k ) (cnt_1,cnt_2,cnt_3,...,cnt_{k-1},cnt_{k}) (cnt1,cnt2,cnt3,...,cntk1,cntk)是每种牌的张数。那么很显然,X 也应该是这些 c n t 1 , c n t 2 , c n t 3 , . . . , c n t k − 1 , c n t k {cnt_1,cnt_2,cnt_3,...,cnt_{k-1},cnt_{k}} cnt1,cnt2,cnt3,...,cntk1,cntk 的约数。 即, X = g c d { c n t 1 , c n t 2 , c n t 3 , . . . , c n t k − 1 , c n t k } X = gcd\{ cnt_1,cnt_2,cnt_3,...,cnt_{k-1},cnt_{k} \} X=gcd{cnt1,cnt2,cnt3,...,cntk1,cntk}

最后我们只需要判断是否 X > = 2 X >= 2 X>=2 即可。

时间复杂度: O ( n l o g C ) O(nlogC) O(nlogC) C = m a x { c n t 1 , c n t 2 , c n t 3 , . . . , c n t k − 1 , c n t k } C = max\{ cnt_1,cnt_2,cnt_3,...,cnt_{k-1},cnt_{k} \} C=max{cnt1,cnt2,cnt3,...,cntk1,cntk}

C++代码:

class Solution {
public:
    bool hasGroupsSizeX(vector<int>& deck) {
        unordered_map<int,int> cnt;
        for(auto x:deck) cnt[x]++;

        int X = 0;
        for(auto [_,v]:cnt) X = gcd(X,v);

        return X >= 2;
    }
};


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值