前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >leetcode464. Can I Win

leetcode464. Can I Win

作者头像
眯眯眼的猫头鹰
发布2020-05-11 17:33:29
2910
发布2020-05-11 17:33:29
举报

题目要求

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.

现在有1~n这n个整数,两个人轮流从这n个数中任意选1个数(数字不能重复选择),假如两个人都用最优方法来选取数字,问玩家一是否一定能够获胜。

思路和代码

像这种轮流选择的题目,其实通过深度优先遍历的方式来穷尽所有的结果,就一定可以的得出结论。但是穷尽可能会出现O(n!)的时间复杂度并导致超市,因此尽可能的记录过程中得出的结论就可以提高时间复杂度。

这题的中间过程有哪些呢:

  1. 剩余还没有选择的数字
  2. 想要得到的目标数字

但是其实我们可以知道,2可以通过(1~n)的数字和减去所有已经选择的数字得出,因此我们只要记录中间结果1即可。而中间结果如何记录呢?可以通过位式图来记录每一位被选择的情况,以及这种选择情况是否一定能够让第一个选择的玩家获胜。举个例子,如1~5,其中选中了(1,3),则位式图为00101.

代码如下:

代码语言:javascript
复制
    Map<Integer, Boolean> map = new HashMap<>();

    public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
        if (desiredTotal <= 0) return true;
        int sum = (maxChoosableInteger + 1) * maxChoosableInteger / 2;
        if (sum < desiredTotal) return false;
        boolean[] selected = new boolean[maxChoosableInteger+1];
        return helper(desiredTotal, selected);
    }

    public boolean helper(int desiredTotal, boolean[] selected) {
        if (desiredTotal <= 0) return false;
        int symbol = format(selected);
        if (map.containsKey(symbol)) {
            return map.get(symbol);
        }
        int size = selected.length;
        for (int i = 1 ; i< size ; i++) {
            if (!selected[i]) {
                selected[i] = true;
                if (!helper(desiredTotal-i, selected)) {
                    selected[i] = false;
                    map.put(symbol, true);
                    return true;
                }
                selected[i] = false;
            }
        }
        map.put(symbol, false);
        return false;
    }

    public int format(boolean[] selected) {
        int symbol = 0;
        for (boolean select : selected) {
            symbol <<= 1;
            if (select) {
                symbol |= 1;
            }
        }
        return symbol;
    }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目要求
  • 思路和代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档