2029.石子游戏 IX-LeetCode

难度:中等

目录

一、问题描述

二、解题思想

三、解题

1、判断极端情况

2、代码实现


一、问题描述

这里我直接采用的LeetCode上面的问题描述。

        Alice 和 Bob 再次设计了一款新的石子游戏。现有一行 n 个石子,每个石子都有一个关联的数字表示它的价值。给你一个整数数组 stones ,其中 stones[i] 是第 i 个石子的价值。

         Alice 和 Bob 轮流进行自己的回合,Alice 先手。每一回合,玩家需要从 stones 中移除任一石子。

  • 如果玩家移除石子后,导致 所有已移除石子 的价值 总和 可以被 3 整除,那么该玩家就 输掉游戏 。
  • 如果不满足上一条,且移除后没有任何剩余的石子,那么 Bob 将会直接获胜(即便是在 Alice 的回合)。

假设两位玩家均采用 最佳 决策。如果 Alice 获胜,返回 true ;如果 Bob 获胜,返回 false 

下面给出示例:

 提示:

  • 1 <= stones.length <= 105
  • 1 <= stones[i] <= 104

二、解题思想

将所有 stones 的价值全部跟 3 求余后,那么所有石子的价值只有三种 0、1、2 :

  • 可以被 3 整除的 记为 0 用 zeroQuantity表示其个数。
  • 不能被 3 整除的余 1 记为 1用 oneQuantity 表示其个数。
  • 不能被 3 整除的余 2 记为 3用 twoQuantity 表示其个数。

要想总价值不能被 3 整除,在Alice先手的且没有zeroQuantity的情况下:

  • 如果Alice拿 1 那么顺序只能是 1121212121......。
  • 如果Alice拿 2 那么顺序只能是 2212121212......。

根据以上情况得出Alice的决策后果

  • 如果Alice起手拿 1 那么,Alice后面只能拿2,Bob后面只能拿1。
  • 如果Alice起手拿 2 那么,Alice后面只能拿1,Bob后面只能拿2。

        现在来考虑 0 的情况 ,先手不能拿 0 ,因为0直接就可以被3整除,那么除了先手,之后都可以拿 0 ,我们不妨假设所有的 0 都是最后取,即把所有的 1 和 2 全部取完后 或者剩下的不论取啥都能够使得总价值被 3 整除,此时剩下的最后两人轮流取 0 。

0很独特,奇数个0可以视为反转了Alice的决策后果即有奇数个0时:

  • 如果Alice起手拿 1 那么,Alice后面只能拿1,Bob后面只能拿2。
  • 如果Alice起手拿 2那么,Alice后面只能拿2,Bob后面只能拿1。

zeroQuantity为偶数时:

  • 只有一个 1 或 一个 2 (Bob赢得游戏,因为被取光了)
  • 当有超过一个1 和超过一个2时,Alice能够根据最佳觉得选择先手拿什么来让自己取得胜利。(Alice赢得游戏,因为根据决策后果:Alice可以让对手拿少的那个)
  • 例如:
  1. [1,1,2,2,1] 顺序为:2 2 1 1 (Alice赢得游戏,Bob拿的总价值可以被3整除)
  2. [1,1,1,1,1,2,2,2] 顺序为 2 2 1 2 1 1 (Alice赢得游戏,Bob拿总价值可以被3整除)
  3. 2 比1 多的情况则同理

zeroQuantity为奇数时:

以上Alice的决策后果则被反转给自己了。

例如:

  1. [1,1,1,2,2,0] 顺序为:2 2 1 0 1 (Bob赢得游戏,此时Alice拿的总价值可以被3整除)

但是当 oneQuantity twoQuantity  的数量差在2以上时 奇数个0将失效:

  1. [1,1,1,1,2,0] 顺序为 :1 1 2 1 0 1 或 1 1 0 2 1 1  此时(Alice赢得游戏,Bob拿的总价值可以被3整除)

三、解题

1、判断极端情况

        此题无特殊极端情况。

2、代码实现

bool stoneGameIX(vector<int>& stones) {
        if(stones.size() == 1){
            return false;
        }
        int zeroQuantity = 0, oneQuantity = 0, twoQuantity = 0;
        for(auto &it: stones){
            it = it % 3;
            if(it == 0){
                zeroQuantity++;
            }else if(it == 1){
                oneQuantity++;
            }else if(it == 2){
                twoQuantity++;
            }
        }
        if(!(zeroQuantity%2)){
            return oneQuantity>=1 && twoQuantity>=1;
        }
        return (oneQuantity-twoQuantity>2) || (twoQuantity-oneQuantity>2);
    }

        

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Alkaid_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值