leetcode_914_卡牌分组_每日一题

914.卡牌分组

题目

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

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

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

思路:最大公约数

  根据题意,通过判断数组中每个数出现的次数,如[1,1,2,2,2,2],每个数出现次数为2、4,则获取最小出现次数2,依次去对每个出现次数取余即可。

  进一步思考,当[1,1,1,1,2,2,2,2]时,每个数出现次数为4、6,然而此样例为true,因为它们最大公约数为2,可以通过求取出现次数的最大公约数。

  再进一步思考,当出现次数为14、21、22时,14和21的最大公约数为7,而14和22最大公约数为2,这个用例为false,由于需要对所有数进行均匀划分,所以,应该对于所有出现次数取最大公约数,即,让一个变量min_s来保存最大公约数,依次用min_s去和每个出现次数取最大公约数,min_s最后结果不为0,则返回true。

  程序思路:

    对数组进行排序

    计数每个数出现的个数,塞进vector里面

    用min_s等于第一个vector值,然后依次求min_s与vector中每个数的最大公约数

import java.util.Vector;
class Solution {
    public int gcd(int m, int n){
        return n==0 ? m:gcd(n, m%n);
    }
    public boolean hasGroupsSizeX(int[] deck) {
        Vector<Integer> v = new Vector<Integer>();
        Arrays.sort(deck);			//排序
        int q = deck[0], sum = 0;
        for(int i:deck){			//对deck中每个出现次数计数,并存入v
            if(i == q)  sum++;
            else{
                v.addElement(sum);
                sum = 1;
                q = i;
            }
        }
        v.addElement(sum);	//添加最后一个数出现的次数
        int min_s = (int)v.get(0);	//初始化最大公约数
        for(int i = 0; i < v.size(); i++){
            min_s = gcd((int)v.get(i), min_s);	//计算min_s与vector中每个数的最大公约数
            if(min_s == 1)    return false;
        }
        return true;
    }
}
优化

  由于vector需要额外占用空间,并且调用数据时间过长,可以用已经遍历过的deck数组进行存储vector中的数据,只需要额外利用一个len变量即可。

import java.util.Vector;
class Solution {
    public int gcd(int m, int n){
        return n==0 ? m:gcd(n, m%n);
    }
    public boolean hasGroupsSizeX(int[] deck) {
        Arrays.sort(deck);		//排序
        int q = deck[0], sum = 0, len = 0;
        for(int i:deck){			//对deck中每个出现次数计数,并存入v
            if(i == q)  sum++;
            else{
                deck[len++] = sum;
                sum = 1;
                q = i;
            }
        }
        deck[len++] = sum;	//添加最后一个数出现的次数
        int min_s = deck[0];	//初始化最大公约数
        for(int i = 0; i < len; i++){
            min_s = gcd(deck[i], min_s);
            if(min_s == 1)    return false;	//计算min_s与vector中每个数的最大公约数
        }
        return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

佳鑫大大

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值