[LeetCode] Hand of Straights 一手顺子牌
Alice has a hand of cards, given as an array of integers.
Now she wants to rearrange the cards into groups so that each group is size W, and consists of W consecutive cards.
Return true if and only if she can.
Example 1:
Input: hand = [1,2,3,6,2,3,4,7,8], W = 3
Output: true
Explanation: Alice'shandcan be rearranged as[1,2,3],[2,3,4],[6,7,8]
Example 2:
Input: hand = [1,2,3,4,5], W = 4
Output: false
Explanation: Alice'shandcan't be rearranged into groups of4
Note:
1 <= hand.length <= 100000 <= hand[i] <= 10^91 <= W <= hand.length
这道题说是我们在打扑克牌,是否能将手里的牌都以顺子的形式出完。在打拐3挖坑或者斗地主的时候,顺子牌在后期的威力是蛮大的,某些人手里憋了一把牌,结果到后期找个机会上手了之后,直接一把甩完,看的手中只有一把单牌的博主是目瞪口呆。其实到了后期,大家手中都没啥牌了的时候,就算是很小的连牌,也不一定能要得起,而划单是最没前途的出法,所以要尽量将手中的牌都组成顺子丢出去。这里给了一个W,规定了顺子的最小长度,那么我们就拿例子1来模拟下打牌吧,首先摸到了牌之后,肯定要先整牌,按从小到大的顺序排列,这里就不考虑啥3最大,4最小啥的,就统一按原始数字排列吧:
1 2 2 3 3 4 6 7 8
好,下面要来组顺子,既然这里是3张可连,那么从最小的开始连呗。其实这道题还是简化了许多,真正打牌的时候,即便是3张起连,那么连4张5张都是可以的,可以这里限定了只能连W张,就使得题目变简单了。我们用贪婪算法就可以了,首先从1开始,那么一定得有2和3,才能起连,若少了任何一个,都可以直接返回false,好那么取出这三张后,手里还有:
2 3 4 6 7 8
那么从当前手里的最小的牌2开始起连,那么手里必须要有3和4,若少了任何一个,都可以直接返回 false,好那么取出这三张后,手里还有:
6 7 8
从当前手里的最小的牌6开始起连,那么手里必须要有7和8,若少了任何一个,都可以直接返回 false,好那么取出这三张后,手里没牌了,我们成功的连完了所有的牌。分析这个过程,不难发现,由于牌可以重复,所以要统计每张牌出现的次数,同时还要给牌按大小排序,用 TreeMap 来建立牌的大小和其出现次数之间的映射就最好不过了,利用了其可以按 key 值排序的特点。首先遍历手中牌,建立映射。然后开始 while 循环,条件是 TreeMap 不为空,然后去除最小的那张牌,然后遍历能组成顺子的W张牌,若没有直接返回 true,有的话,则映射值自减1,若映射值为0了,则从 TreeMap 中移除该映射对儿即可,while 循环退出后返回 true,参见代码如下:
解法一:
class Solution {
public:
bool isNStraightHand(vector<int>& hand, int W) {
map<int, int> m;
for (int i : hand) ++m[i];
while (!m.empty()) {
int start = m.begin()->first;
for (int i = ; i < W; ++i) {
if (!m.count(start + i)) return false;
if (--m[start + i] == ) m.erase(start + i);
}
}
return true;
}
};
我们也可以不对 TreeMap 进行删除操作,而是直接修改其映射值,在建立好映射对儿之后,不用 while 循环,而是遍历所有的映射对儿,若某个映射值为0了,直接跳过。然后还是遍历能组成顺子的W张牌,若某张牌出现的次数小于顺子起始位置的牌的个数,则直接返回 false,因为肯定会有起始牌剩余,无法全组成顺子,这样还避免了上面解法中一张一张减的操作,提高了运算效率。然后映射值减去起始牌的个数,最后 for 循环退出后,返回 true,参见代码如下:
解法二:
class Solution {
public:
bool isNStraightHand(vector<int>& hand, int W) {
map<int, int> m;
for (int i : hand) ++m[i];
for (auto a : m) {
if (a.second == ) continue;
for (int i = a.first; i < a.first + W; ++i) {
if (m[i] < a.second) return false;
m[i] = m[i] - a.second;
}
}
return true;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/846
参考资料:
https://leetcode.com/problems/hand-of-straights/
https://leetcode.com/problems/hand-of-straights/discuss/135700/Short-Java-solution!
https://leetcode.com/problems/hand-of-straights/discuss/135598/C%2B%2BJavaPython-O(MlogM)-Complexity
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Hand of Straights 一手顺子牌的更多相关文章
- [Swift]LeetCode846. 一手顺子 | Hand of Straights
Alice has a hand of cards, given as an array of integers. Now she wants to rearrange the cards into ...
- [LeetCode] Shuffle an Array 数组洗牌
Shuffle a set of numbers without duplicates. Example: // Init an array with set 1, 2, and 3. int[] n ...
- leetcode(js)算法之914卡牌分组
给定一副牌,每张牌上都写着一个整数. 此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组: 每组都有 X 张牌. 组内所有的牌上都写着相同的整数. 仅当你可选的 X > ...
- Leetcode(870)-优势洗牌
给定两个大小相等的数组 A 和 B,A 相对于 B 的优势可以用满足 A[i] > B[i] 的索引 i 的数目来描述. 返回 A 的任意排列,使其相对于 B 的优势最大化. 示例 1: 输入: ...
- Swift LeetCode 目录 | Catalog
请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift 说明:题目中含有$符号则为付费题目. 如 ...
- C#LeetCode刷题-Map
Map篇 # 题名 刷题 通过率 难度 846 一手顺子 33.7% 中等 855 考场就座 20.8% 中等
- 德州扑克AK打法攻略
AK是所有德扑网游中最受争议的底牌,也是一副令人又爱又恨的底牌.<德州扑克培训大师>根据国内德州扑克网游特性,为大家制作了第一套AK打法攻略,希望所有玩家从今天开始能正确认识AK,发挥AK ...
- 我是一只IT小小鸟----读书笔记
人生如同打牌,能抓到一手好牌固然是运气好,但重要的是,你不能靠运气生活,而要琢磨怎样把手上这把看上去“不怎么样的”牌打好. 要了解一种主流的软件开发与运行平台,熟练掌握一种开发工具,这样就具备了进行开 ...
- [Aaronyang] 写给自己的WPF4.5 笔记[2依赖属性]
人生的意义不在于拿一手好牌,而在于打好一手坏牌 --Aaronyang的博客(www.ayjs.net)-www.8mi.me =============时隔两年后再看WPF========== 因为 ...
随机推荐
- rabbitmq - (消息队列) 的基本原理介绍
介绍 MQ全称为Message Queue, 是一种分布式应用程序的的通信方法,它是消费-生产者模型的一个典型的代表,producer往消息队列中不断写入消息,而另一端consumer则可以读取或者订 ...
- matlab读取图片的异常表现
在对人脸图片进行对齐时,发现有两张人脸图片一直检测不到人脸,但这两张图片中的人脸明明很好检测(证件照),经过 排查,最终发现问题所在:图片的格式不对. img = imread("**.jp ...
- 《剑指offer》扑克牌顺子
本题来自<剑指offer> 反转链表 题目: 思路: C++ Code: Python Code: 总结:
- js中的严格模式和非严格模式的比较
前言 es5的严格模式是采用具有限制性JavaScript变体的一种方式,从而使代码显示地脱离'懒散模式/非严格模式' 严格模式 严格模式通过抛出错误来消除一些原有静默错误 严格模式修复了一些导致Ja ...
- 深入理解position属性&containing block
一.包含块(Containing Block) 要讲position,首先就涉及到一个概念:包含块. 1.包含块介绍 包含块简单理解就是一个定位参考块,就是"大盒子里套小盒子"中那 ...
- Net MVC使用datatables插件
基本用法 1 - 引入js和css <link href="https://cdn.bootcss.com/datatables/1.10.19/css/dataTables.boot ...
- Excel—数组
SUMPRODUCT(数组求和函数)和SUM是一样的,只不过数组写完公式后需要三键合一出结果(ctrl+shift+enter),用SUMPRODUCT写公式写完直接敲击enter就行了 函数语法:S ...
- 理解WindowManagerService
--摘自<Android进阶解密> *WMS的职责* 1)窗口管理 WMS负责窗口的启动.添加和删除,另外窗口的大小和层级也是由WMS进行管理的 2)窗口动画 WMS的动画子系统Windo ...
- 【redis】在dotnet core下的redis的使用
1.Install-Package Microsoft.Extensions.Caching.Redis -Version 2.2.0 2.注入 services.AddDistributedRedi ...
- 创建线程的一般方式和匿名内部类方式对比——继承thread类,重写run()方法
第一种:继承thread类,重写run()方法 一般方式:Demo01.java /** * 创建线程的第一种方式:继承thread类,重写run()方法 * * @author :liuqi * @ ...