In the "100 game," two players take turns adding, to a running total, any integer from 1..10. The player who first causes the running total to reach or exceed 100 wins.

What if we change the game so that players cannot re-use integers?

For example, two players might take turns drawing from a common pool of numbers of 1..15 without replacement until they reach a total >= 100.

Given an integer maxChoosableInteger and another integer desiredTotal, determine if the first player to move can force a win, assuming both players play optimally.

You can always assume that maxChoosableInteger will not be larger than 20 and desiredTotal will not be larger than 300.

Example

Input:
maxChoosableInteger = 10
desiredTotal = 11 Output:
false Explanation:
No matter which integer the first player choose, the first player will lose.
The first player can choose an integer from 1 up to 10.
If the first player choose 1, the second player can only choose integers from 2 up to 10.
The second player will win by choosing 10 and get a total = 11, which is >= desiredTotal.
Same with other integers chosen by the first player, the second player will always win.

这道题给了我们一堆数字,然后两个人,每人每次选一个数字,看数字总数谁先到给定值,有点像之前那道 Nim Game,但是比那题难度大。我刚开始想肯定说用递归啊,结果写完发现 TLE 了,后来发现我们必须要优化效率,使用 HashMap 来记录已经计算过的结果。我们首先来看如果给定的数字范围大于等于目标值的话,直接返回 true。如果给定的数字总和小于目标值的话,说明谁也没法赢,返回 false。然后我们进入递归函数,首先我们查找当前情况是否在 HashMap 中存在,有的话直接返回即可。我们使用一个整型数按位来记录数组中的某个数字是否使用过,我们遍历所有数字,将该数字对应的 mask 算出来,如果其和 used 相与为0的话,说明该数字没有使用过,我们看如果此时的目标值小于等于当前数字,说明已经赢了,或者调用递归函数,如果返回 false,说明也是第一个人赢了。为啥呢,因为当前已经选过数字了,此时就该对第二个人调用递归函数,只有返回的结果是 false,我们才能赢,所以此时我们 true,并返回 true。如果遍历完所有数字,标记 false,并返回 false,参见代码如下:

class Solution {
public:
bool canIWin(int maxChoosableInteger, int desiredTotal) {
if (maxChoosableInteger >= desiredTotal) return true;
if (maxChoosableInteger * (maxChoosableInteger + ) / < desiredTotal) return false;
unordered_map<int, bool> m;
return canWin(maxChoosableInteger, desiredTotal, , m);
}
bool canWin(int length, int total, int used, unordered_map<int, bool>& m) {
if (m.count(used)) return m[used];
for (int i = ; i < length; ++i) {
int cur = ( << i);
if ((cur & used) == ) {
if (total <= i + || !canWin(length, total - (i + ), cur | used, m)) {
m[used] = true;
return true;
}
}
}
m[used] = false;
return false;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/464

类似题目:

Nim Game

Flip Game II

Guess Number Higher or Lower II

Predict the Winner

参考资料:

https://leetcode.com/problems/can-i-win/

https://leetcode.com/problems/can-i-win/discuss/95283/brute-force-and-memoization

https://leetcode.com/problems/can-i-win/discuss/95277/Java-solution-using-HashMap-with-detailed-explanation

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Can I Win 我能赢吗的更多相关文章

  1. [LeetCode] 464. Can I Win 我能赢吗

    In the "100 game," two players take turns adding, to a running total, any integer from 1.. ...

  2. Leetcode: Can I Win

    In the "100 game," two players take turns adding, to a running total, any integer from 1.. ...

  3. 464 Can I Win 我能赢吗

    详见:https://leetcode.com/problems/can-i-win/description/ C++: class Solution { public: bool canIWin(i ...

  4. python 练习 2

    #!/usr/bin/python # -*- coding: utf-8 -*- from random import shuffle class caigame: win=False flag=F ...

  5. D - Football (aka Soccer)

    Football the most popular sport in the world (americans insist to call it "Soccer", but we ...

  6. 某软件大赛C#版考题整理——【编程题】

    三.编程题(4小题共40.0分)程序及结果写入对应文框内 1. 孪生素数查找程序. 所谓孪生素数指的是间隔为2 的相邻素数,就像孪生兄弟.最小的孪生素数是(3, 5),在100 以内的孪生素数还有 ( ...

  7. Internet History, Technology and Security (Week3)

    Week3. Welcome to week 3! This is our fourth and final week of History where we make the connection ...

  8. 状态压缩 - LeetCode #464 Can I Win

    动态规划是一种top-down求解模式,关键在于分解和求解子问题,然后根据子问题的解不断向上递推,得出最终解 因此dp涉及到保存每个计算过的子问题的解,这样当遇到同样的子问题时就不用继续向下求解而直接 ...

  9. [Swift]LeetCode464. 我能赢吗 | Can I Win

    In the "100 game," two players take turns adding, to a running total, any integer from 1.. ...

随机推荐

  1. Oracle 11.2.0.4单实例打PSU,OJVM PSU补丁快速参考

    写在前面: 1.Oracel打每个补丁的操作有时存在差异,所以不管多熟悉,都应该在打任何补丁之前阅读新补丁中附带的readme. 2.Oracle每季度都会更新一个最新的PSU,本文最新指的是当前最新 ...

  2. 【分布式】Zookeeper使用--开源客户端

    一.前言 上一篇博客已经介绍了如何使用Zookeeper提供的原生态Java API进行操作,本篇博文主要讲解如何通过开源客户端来进行操作. 二.ZkClient ZkClient是在Zookeepe ...

  3. CSS知识总结(二)

    CSS的选择符分成: 1. 通配选择符 2. 元素选择符 3. 群组选择符 4. 关系选择符 5. id及class选择符 6. 伪类选择符 7. 属性选择符 8. 伪对象选择符 1.通配选择符(*) ...

  4. STM32 NVIC配置详解

    例程:  /* Configure one bit for preemption priority */  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1) ...

  5. 『.NET Core CLI工具文档』(十一)dotnet-test

    说明:本文是个人翻译文章,由于个人水平有限,有不对的地方请大家帮忙更正. 原文:dotnet-test 翻译:dotnet-test 名称 dotnet-test - 使用配置的测试运行器运行单元测试 ...

  6. helios架构详解(一)服务器端架构

    看了“菜鸟耕地”的”.NET开源高性能Socket通信中间件Helios介绍及演示“,觉得这个东西不错.但是由于没有网络编程知识,所以高性能部分我就讲不出来了,主要是想根据开源代码跟大家分享下Heli ...

  7. 再谈JavaScript闭包及应用

    .title-bar { width: 80%; height: 35px; padding-left: 35px; color: white; line-height: 35px; font-siz ...

  8. Struts+Spring+Hibernate项目的启动线程

    在Java Web项目中,经常要在项目开始运行时启动一个线程,每隔一定的时间就运行一定的代码,比如扫描数据库的变化等等.要实现这个功能,可以现在web.xml文件中定义一个Listener,然后在这个 ...

  9. SpringMVC 入门

    MVC 简介 1.MVC 是一种架构模式 程序分层,分工合作,既相互独立,又协同工作,分为三层:模型层.视图层和控制层 2.MVC 是一种思考方式 View:视图层,为用户提供UI,重点关注数据的呈现 ...

  10. 记录一次bug解决过程:eclipse Installed JREs 配置引出的问题

    一 总结 eclipse Installed JREs 配置引出的问题:编译以来JDK,不是JRE spring boot内嵌tomcat运行程序,tomcat:run 二 Bug描述:eclipse ...