leetcode 464. 我能赢吗?

leetcode 464. 我能赢吗?

原题链接:https://leetcode-cn.com/problems/can-i-win

在 “100 game” 这个游戏中,两名玩家轮流选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和达到 100 的玩家,即为胜者。

如果我们将游戏规则改为 “玩家不能重复使用整数” 呢?

例如,两个玩家可以轮流从公共整数池中抽取从 1 到 15 的整数(不放回),直到累计整数和 >= 100。

给定一个整数 maxChoosableInteger (整数池中可选择的最大数)和另一个整数 desiredTotal(累计和),判断先出手的玩家是否能稳赢(假设两位玩家游戏时都表现最佳)?

你可以假设 maxChoosableInteger 不会大于 20, desiredTotal 不会大于 300

示例
输入:
maxChoosableInteger = 10
desiredTotal = 11

输出:
false

解释:
无论第一个玩家选择哪个整数,他都会失败。
第一个玩家可以选择从 1 到 10 的整数。
如果第一个玩家选择 1,那么第二个玩家只能选择从 2 到 10 的整数。
第二个玩家可以通过选择整数 10(那么累积和为 11 >= desiredTotal),从而取得胜利.
同样地,第一个玩家选择任意其他整数,第二个玩家都会赢。

输入
maxChoosableInteger = 10
desiredTotal = 5

输出
true

解释:
只要第一个玩家选择 >= 5的数,都可以稳赢

输入:
maxChoosableInteger = 5
desiredTotal = 100

输出:
false

解释:
无论两个玩家怎么选择,都不可能达到100,因此都算输

稳赢的意思只要存在一个数,当我选择这个数,无论对方怎么选择,我都稳赢。
稳输的意思是,穷尽所有选择,都无法找出一个数能让自己稳赢。

当maxChoosableInteger >= desiredTotal 时,第一个人先选择,那么一定稳赢,
当所有数字的累计和 < desiredTotal时,第一个人无论怎么选,两个人都是输,因为不可能达到

根据定义,如果第一个人要稳赢,那么只要在选择了一个数之后,对方稳输就可以了,所以这是一个递归问题,不过我们需要记录哪些数字被选择了,这里采用了一个小技巧,使用位运算来存储当前哪些数字被选择
如果maxChoosableInteger = 1, 那么当1被选择,我们用1表示,未被选择用0表示
如果maxChoosableInteger =2, 如果都未选择用00表示,如果1被选择用01表示,2被选择用10表示,如果都被选择,则用11表示。

因此 选择第i个数,可以用state | 1 << i-1来表示,而判断第i个数是否被选择,可以用 (state & 1 << i-1) == 0来判断,等于0则未被选择,不等于0则已经被选择过了。
定义dp数组,用来存储在状态state下,是否能够稳赢,因为递归会有很多重复计算产生,所以通过dp数组消除重复计算。

下面上代码:

class Solution {
    public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
        if(maxChoosableInteger > desiredTotal){
            return true;
        }
        if((maxChoosableInteger+1)*maxChoosableInteger/2 < desiredTotal){
            return false;
        }

        return helper(maxChoosableInteger,desiredTotal,new Boolean[(1 << maxChoosableInteger)], 0);
    }

    private boolean helper(int maxChoosableInteger, int desiredTotal, Boolean[] dp, int state){
        if(dp[state] != null){
            return dp[state];
        }

        for(int i=1; i<=maxChoosableInteger; i++){
            //如果i已经使用过,continue;
            if(((1 << i-1) & state) != 0){
                continue;
            }

            // 当前的值大于等于目标值的时候,说明稳赢
            // 或者 当选择了当前值, 对方稳输的话,自己也是稳赢。
            int curState = (1 << i-1) | state;
            if(i >= desiredTotal || !helper(maxChoosableInteger, desiredTotal-i, dp, curState)){
                dp[state] = true;
                return dp[state];
            }
        }

        return dp[state] = false;
    }
}
### 如何在 VSCode 中安装配置 LeetCode 插件以及 Node.js 运行环境 #### 安装 LeetCode 插件 在 VSCode 的扩展市场中搜索 `leetcode`,找到官方提供的插件并点击 **Install** 按钮进行安装[^1]。如果已经安装过该插件,则无需重复操作。 #### 下载与安装 Node.js 由于 LeetCode 插件依赖于 Node.js 环境,因此需要下载并安装 Node.js。访问官方网站 https://nodejs.org/en/ 并选择适合当前系统的版本(推荐使用 LTS 版本)。按照向导完成安装流程后,需确认 Node.js 是否成功安装到系统环境中[^2]。 可以通过命令行运行以下代码来验证: ```bash node -v npm -v ``` 上述命令应返回对应的 Node.js npm 的版本号。如果没有正常返回版本信息,则可能未正确配置环境变量。 #### 解决环境路径问题 即使完成了 Node.js 的安装,仍可能出现类似 “LeetCode extension needs Node.js installed in environment path” 或者 “command ‘leetcode.toggleLeetCodeCn’ not found” 的错误提示[^3]。这通常是因为 VSCode 未能识别全局的 Node.js 路径或者本地安装的 nvm 默认版本未被正确加载[^4]。 解决方法如下: 1. 手动指定 Node.js 可执行文件的位置 在 VSCode 设置界面中输入关键词 `leetcode`,定位至选项 **Node Path**,将其值设为实际的 Node.js 安装目录下的 `node.exe` 文件位置。例如:`C:\Program Files\nodejs\node.exe`。 2. 使用 NVM 用户管理工具调整默认版本 如果通过 nvm 工具切换了不同的 Node.js 版本,请确保设置了默认使用的版本号。可通过以下指令实现: ```bash nvm alias default <version> ``` 重新启动 VSCode 后测试功能键是否恢复正常工作状态。 --- #### 配置常用刷题语言 最后一步是在 VSCode 设置面板中的 LeetCode 插件部分定义个人习惯采用的主要编程语言作为默认提交方式之一。这样可以减少频繁修改编码风格的时间成本。 --- ### 总结 综上所述,要在 VSCode 上顺利启用 LeetCode 插件及其关联服务,除了基本插件本身外还需额外准备支持性的后台框架——即 Node.js 应用程序引擎;同时针对特定场景下产生的兼容性障碍采取针对性措施加以修正即可达成目标[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值