这是悦乐书的第352次更新,第377篇原创

01 看题和准备

今天介绍的是LeetCode算法题中Easy级别的第214题(顺位题号是914)。在一副牌中,每张牌上都写有一个整数。

当且仅当您可以选择X >= 2时才返回true,以便可以将整个牌组分成一组或多组牌,其中:

  • 每组都有X张牌。

  • 每组中的所有牌都具有相同的整数。

例如:

输入:[1,2,3,4,4,3,2,1]

输出:true

说明:可能的分区[1,1],[2,2],[3,3],[4,4]

输入:[1,1,1,2,2,2,3,3]

输出:false

说明:没有可能的分区。

输入:[1]

输出:false

说明:没有可能的分区。

输入:[1,1]

输出:true

说明:可能的分区[1,1]

输入:[1,1,2,2,2,2]

输出:true

说明:可能的分区[1,1],[2,2],[2,2]

注意

  • 1 <= deck.length <= 10000

  • 0 <= deck[i] <10000

02 第一种解法

题目的意思是将数组deck中的元素进行分组,值相等的划分为同一组,每一组中的元素个数都相等,且大于等于2。我们可以使用一个HashMap,以deck中的元素为key,以其出现次数为value,对HashMapvalue值进行遍历。

最理想的情况,HashMap中只有一组key-value,但测试用例中肯定不会这么轻易让你AC。来看几组例子分析下规律:

{1,1,1,2,2,2,3,3}
{{1,1,1},{2,2,2},{3,3}} --> {3,3,2} {1,1,2,2,2,2,3,3,3,3,3,3}
{{1,1},{2,2,2,2},{3,3,3,3,3,3}} --> {2,4,6}

第一个例子中,他们的最大公约数为1,即分组的组数存在奇偶分布的情况。

第二个例子中,他们的最大公约数为2,即分组的组数都是偶数,并且对于其中的4个2和6个3,是还可以继续拆分的,4个2拆成两组2个2,6个3拆成三组2个3。

因此,我们只需要判断HashMap中每对数据的最大公约数是不是等于1即可。

public boolean hasGroupsSizeX(int[] deck) {
if (deck.length < 2) {
return false;
}
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int num : deck) {
map.put(num, map.getOrDefault(num, 0)+1);
}
int count = 0;
for (Integer value : map.values()) {
if (value < 2) {
return false;
}
if (count == 0) {
count = value;
} else {
if (count != value) {
int gcd = 1;
for (int i=1; i<= count || i<=value; i++) {
if (count%i == 0 && value%i == 0) {
gcd = i;
}
}
if (gcd == 1) {
return false;
}
}
}
}
return true;
}

03 第二种解法

思路和第一种解法一样,只是将其中部分代码抽离了出来,并且简化了一些if-else判断。

public boolean hasGroupsSizeX2(int[] deck) {
if (deck.length < 2) {
return false;
}
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int num : deck) {
map.put(num, map.getOrDefault(num, 0)+1);
}
int min = 10001;
for (Integer num : map.values()) {
min = Math.min(min, num);
}
if (min == 1) {
return false;
}
for (Integer num : map.values()) {
if (getGCD(min, num) == 1) {
return false;
}
}
return true;
} public int getGCD(int a, int b) {
int gcd = 1;
for (int i=1; i<= a || i<=b; i++) {
if (a%i == 0 && b%i == 0) {
gcd = i;
}
}
return gcd;
}

04 第三种解法

因为限定了数组deck中元素值范围,因此我们可以使用一个整型数组count来计算deck中各元素的出现次数,然后遍历count中的元素,求出他们的最大公约数,只要有一对数的最大公约数等于1,就直接返回false。

public boolean hasGroupsSizeX3(int[] deck) {
int[] count = new int[10001];
for (int num : deck) {
count[num]++;
}
int temp = -1;
for (int num : count) {
if (num > 0) {
if (num < 2) {
return false;
}
if (temp == -1) {
temp = num;
} else {
if (getGCD(temp, num) == 1) {
return false;
}
}
}
}
return true;
} public int getGCD(int a, int b) {
int gcd = 1;
for (int i=1; i<= a || i<=b; i++) {
if (a%i == 0 && b%i == 0) {
gcd = i;
}
}
return gcd;
}

05 第四种解法

对第三种解法,我们还可以再优化下,将求最大公约数的方法独立处理,并且用递归处理。

public boolean hasGroupsSizeX4(int[] deck) {
int[] count = new int[10001];
for (int num : deck) {
count[num]++;
}
int tem = count[deck[0]];
for (int num : count) {
if (num > 0) {
tem = gcd(tem, num);
}
}
return tem > 1;
} /**
* 利用递归求a和b的最大公约数
* @param a
* @param b
* @return
*/
public int gcd(int a, int b) {
return a == 0 ? b : gcd(b%a, a);
}

06 小结

算法专题目前已连续日更超过六个月,算法题文章220+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

LeetCode.914-一副牌中的X(X of a Kind in a Deck of Cards)的更多相关文章

  1. [Swift]LeetCode914.一副牌中的X | X of a Kind in a Deck of Cards

    In a deck of cards, each card has an integer written on it. Return true if and only if you can choos ...

  2. [LeetCode] 914. X of a Kind in a Deck of Cards 一副牌中的X

    In a deck of cards, each card has an integer written on it. Return true if and only if you can choos ...

  3. 【LeetCode】914. X of a Kind in a Deck of Cards 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 遍历 最大公约数 日期 题目地址: https:// ...

  4. 53张牌中找出缺少的牌的花色和点数--raid3,4,5,6的容错原理

    一副扑克牌,抽出一张,要求找出抽出的牌的点数和花色. 算法的主要思想就是用异或运算来确定丢的牌的花色.四种花色分别如下表示:红桃用1(二进制0001)表示,黑桃用2(二进制0010)表示,黑桃用4(0 ...

  5. LeetCode 80. 删除排序数组中的重复项 II

    LeetCode 80. 删除排序数组中的重复项 II

  6. LeetCode:删除排序链表中的重复元素【83】

    LeetCode:删除排序链表中的重复元素[83] 题目描述 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次. 示例 1: 输入: 1->1->2 输出: 1->2 示 ...

  7. 【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang)

    [分析]浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang) 今天无意中看到有关Invoke和BeginInvoke的一些资料,不太清楚它们之间 ...

  8. 《流畅的Python》一副扑克牌中的难点

    1.现在在看<流畅的Python>这本书,看了三页就发现,这本书果然不是让新手来入门的,一些很常见的知识点能被这个作者玩出花来, 唉,我就在想,下面要分析的这些的代码,就算我费劲巴拉的看懂 ...

  9. 前端与算法 leetcode 26. 删除排序数组中的重复项

    目录 # 前端与算法 leetcode 26. 删除排序数组中的重复项 题目描述 概要 提示 解析 算法 # 前端与算法 leetcode 26. 删除排序数组中的重复项 题目描述 26. 删除排序数 ...

随机推荐

  1. UVA - 12538 Version Controlled IDE (可持久化treap)

    紫薯例题 #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3f3f3f; ],ch[ ...

  2. h5手机页面注册处理(短信验证)

    //获取验证码 var wait = 60; function time(o) { if(wait == 0) { o.removeAttribute("disabled"); o ...

  3. 阻止默认/冒泡事件(兼容ie)

    (1) 阻止默认事件 function(e){ if(e && e.preventDefault){ e.preventDefault(); }else{ //IE window.ev ...

  4. 网络编程简介(OSI七层协议,TCP协议原理,三次握手与四次挥手)

    目录 网络编程 软件开发架构 C/S架构 B/S架构 网络编程的发展史 互联网协议 1.物理连接层 2.数据链路层 3.网络层 4.传输层 5.应用层 三次握手四次挥手 三次握手建链接 数据传输 四次 ...

  5. buuctf@warmup_csaw_2016

    from pwn import * io=remote('node3.buuoj.cn',27774) io.recvuntil('WOW:') addr=(io.recvuntil('\n')[:- ...

  6. Wpf自动滚动效果

    一.思路 1.使用ScrollView的Scroll.ScrollToVerticalOffset(offset)方法进行滚动 2.ScrollView中放置2个ListView,第一个滚动出边界后, ...

  7. Java多线程和并发(三),Thread类和Runnable接口

    目录 1.Thread和Runnable接口 三.Thread类和Runnable接口 1.Thread和Runnable接口

  8. 【GDSOI2019】滑稽二乘法【数据结构】【LCT】

    Description 点数<=100000,操作数<=200000 Solution 经典的LCT维护子树路径信息的问题. 具体来说,我们对于每一个节点,它在splay上的子树对应了原树 ...

  9. C++入门经典-例3.11-使用if语句来实现根据输入的字符输出字符串

    1:代码如下: // 3.11.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> usin ...

  10. python3笔记二十三:正则表达式之其他函数

    一:学习内容 re.split函数 re.finditer函数 re.sub函数 group()分组 re.compile函数 二:字符串切割---re.split函数 需要导入包:import re ...