914. 卡牌分组

112 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

题目 leetcode.cn/

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

示例

  • 输入:deck = [1,2,3,4,4,3,2,1]; 输出: true
    • 解释: 可行的分组是 [1,1],[2,2],[3,3],[4,4]
  • 输入:deck = [1,1,1,2,2,2,3,3]; 输出: false
    • 解释: 没有满足要求的分组。

提示

  • 1 <= deck.length <= 100000
  • 0 <= deck[i] < 100000

代码

function hasGroupsSizeX(deck: number[]): boolean {
    let newArr = deck.sort((a, b) => { return a - b });
    let result = [];
    for(let i = 0; i < deck.length; i++){
        let first = newArr.indexOf(newArr[i]);
        let end = newArr.lastIndexOf(newArr[i]);
        result.push(end - first + 1);
    }
    let xArray = [... new Set(result)];
    if(Math.min(...xArray) === 1){
        return false
    } else {
        for(let i = 2; i <= Math.max(...xArray); i++){
            for(let j = 0; j < xArray.length; j++){
                if(!Number.isInteger(xArray[j] / i)){
                    break;
                }
                if(j === xArray.length - 1 && Number.isInteger(xArray[j] / i)){
                    return true;
                }
            }
        }
    }
    return false;
};

思路

  • 先分析下题目,首先不知道要分成几个组,但是每个组的牌必须大于1时,并且每个组内的牌是相同的
    • 比如 [1,1,1,1,2,2,2,2,,3,3,3,3],就可以分成六个组[1,1],[1,1],[2,2],[2,2],[3,3],[3,3],也可以分成三个一组[1,1,1,1],[2,2,2,2],[3,3,3,3]
  • 所以必须要保证每个组内的数字都相同
    • 首先将给到的牌排序,方便后面统计每张相同纸牌的个数
    • 然后利用indexOf,lastIndexOf统计相同个数
    • 去除掉相同的个数
    • 如果给到的纸牌最小的张数是一张的话,要么分成一张一组,这样就不符合要求,要么每组大于一张,但是必定会有一组纸牌数字不同,直接返回false
    • 遍历所有的纸牌数量和分组情况,因为分组必须大于等于2,所以循环从2开始,最大范围为最多的牌的张数(包含最大值)
      • 如果有一个数字的数量不能整除分组数,退出当前循环,进行下一次循环
      • 如果每个数字的数量都可以整除分组数,那么是符合条件的,返回true
  • 注意一下分组取值Math.max(...xArray)是小于等于,一定要包括等于,例如[1,1,1,1,2,2,2,2,,3,3,3,3]分成[1,1,1,1],[2,2,2,2],[3,3,3,3],包括了最长个数4