leetcode
leetcode 1801 ~ 1850
石子游戏 IX

石子游戏 IX

难度:

标签:

题目描述

代码结果

运行时间: 85 ms, 内存: 26.6 MB


/*
 * 思路:
 * 1. 计算stones数组中每个石子的价值对3的余数,统计余数为0, 1, 2的个数。
 * 2. 根据不同余数个数的组合情况来判断谁会获胜。
 * 3. Alice和Bob会采取最佳策略进行游戏。
 */
import java.util.Arrays;

public class StoneGame {
    public boolean stoneGame(int[] stones) {
        long count0 = Arrays.stream(stones).filter(stone -> stone % 3 == 0).count();
        long count1 = Arrays.stream(stones).filter(stone -> stone % 3 == 1).count();
        long count2 = Arrays.stream(stones).filter(stone -> stone % 3 == 2).count();
        // 如果count0是偶数,则只要count1和count2均不为零,Alice就可以通过相互抵消来获胜
        if (count0 % 2 == 0) {
            return count1 > 0 && count2 > 0;
        } else {
            // 如果count0是奇数,则需要判断count1和count2之间是否存在一个足够大的差异
            return Math.abs(count1 - count2) > 2;
        }
    }
}

解释

方法:

题解主要通过计算各个石子对3取模的结果,根据其频率来确定Alice是否能够获胜。首先,石子的值对3的余数被分为三类:0, 1, 2。用数组cnt来计数每个类别的石子数量。接下来,根据cnt[0](余数为0的石子数量)是否为偶数,分两种情况考虑:1. 如果cnt[0]是偶数,则分别检查:当选择余数为1的石子开始时,余数为2的石子数量至少要不少于余数为1的石子数量;当选择余数为2的石子开始时,余数为1的石子数量至少要不少于余数为2的石子数量。2. 如果cnt[0]是奇数,则分别检查:当选择余数为1的石子开始时,余数为1的石子数量至少要比余数为2的石子多2;当选择余数为2的石子开始时,余数为2的石子数量至少要比余数为1的石子多2。最后,根据以上条件返回Alice是否可能赢得游戏。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在题解中将石子的值对3取模,并分成三类0, 1, 2来处理?这样的分类有什么特别的意义吗?
在石子游戏IX中,将石子的值对3取模并分成三类0, 1, 2是因为这与游戏的基本规则有关,规则涉及到石子数值的累加和对3的余数。当两名玩家轮流取石子时,他们的目标是避免使得累积的石子数值之和被3整除,因为这将导致游戏立即结束并判输。因此,通过分类这些余数,我们可以更好地分析和预测各种取石子策略的结果,并制定相应的策略来优化胜算。
🦆
题解中提到,如果cnt[0](余数为0的石子数量)为偶数,Alice有赢的可能性。这里为什么会根据cnt[0]的奇偶性来分别处理?
在石子游戏IX中,余数为0的石子特别重要,因为它们直接影响游戏的输赢条件——导致累积和被3整除。当cnt[0]为偶数时,这些石子在游戏中被取走后,不会改变当前的取石子序列对3的总余数,从而保持游戏状态稳定。然而,如果cnt[0]为奇数,每次取一个余数为0的石子,都会使得状态在奇数和偶数之间切换,增加了游戏的不确定性和复杂性。因此,判断cnt[0]的奇偶性是分析Alice是否有赢得可能性的关键步骤。
🦆
在判断Alice是否能赢的逻辑中,为什么当cnt[0]为偶数时,需要检查`cnt[1] >= 1 and cnt[2] >= cnt[1]`这样的条件?
当cnt[0]为偶数时,余数为0的石子不会对游戏的总状态产生影响,因此游戏的胜负主要取决于余数为1和2的石子。检查`cnt[1] >= 1 and cnt[2] >= cnt[1]`的条件意味着Alice可以开始选择余数为1的石子,并且她能够继续游戏直到所有的石子都被选完。这个条件确保了即使Bob尝试通过选择余数为2的石子来改变游戏状态,Alice仍有足够的余数为1的石子来应对,避免使累积和被3整除,从而保持赢面。

相关问题