leetcode刷题记录-2038. 如果相邻两个颜色均相同则删除当前颜色

151 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

前言

今天的第二题难度为中等,乍一看题目好像很难,还是需要查找最优解的博弈论题目,但其实仔细看下去,会发现很简单,算不上中等题。

每日一题

今天的第二题题目是 2038. 如果相邻两个颜色均相同则删除当前颜色,难度为中等

  • 总共有 n 个颜色片段排成一列,每个颜色片段要么是 'A' 要么是 'B' 。给你一个长度为 n 的字符串 colors ,其中 colors[i] 表示第 i 个颜色片段的颜色。

  • Alice 和 Bob 在玩一个游戏,他们 轮流 从这个字符串中删除颜色。Alice 先手 。

  • 如果一个颜色片段为 'A' 且 相邻两个颜色 都是颜色 'A' ,那么 Alice 可以删除该颜色片段。Alice 不可以 删除任何颜色 'B' 片段。

  • 如果一个颜色片段为 'B' 且 相邻两个颜色 都是颜色 'B' ,那么 Bob 可以删除该颜色片段。Bob 不可以 删除任何颜色 'A' 片段。

  • Alice 和 Bob 不能 从字符串两端删除颜色片段。

  • 如果其中一人无法继续操作,则该玩家 输 掉游戏且另一玩家 获胜 。

  • 假设 Alice 和 Bob 都采用最优策略,如果 Alice 获胜,请返回 true,否则 Bob 获胜,返回 false。

 

示例 1:

输入:colors = "AAABABB"
输出:true
解释:
AAABABB -> AABABB
Alice 先操作。
她删除从左数第二个 'A' ,这也是唯一一个相邻颜色片段都是 'A''A' 。

现在轮到 Bob 操作。
Bob 无法执行任何操作,因为没有相邻位置都是 'B' 的颜色片段 'B' 。
因此,Alice 获胜,返回 true

示例 2:

输入:colors = "AA"
输出:false
解释:
Alice 先操作。
只有 2'A' 且它们都在字符串的两端,所以她无法执行任何操作。
因此,Bob 获胜,返回 false

示例 3:

输入:colors = "ABBBBBBBAAA"
输出:false
解释:
ABBBBBBBAAA -> ABBBBBBBAA
Alice 先操作。
她唯一的选择是删除从右数起第二个 'A'ABBBBBBBAA -> ABBBBBBAA
接下来轮到 Bob 操作。
他有许多选择,他可以选择任何一个 'B' 删除。

然后轮到 Alice 操作,她无法删除任何片段。
所以 Bob 获胜,返回 false

 

提示:

  • 1 <= colors.length <= 105
  • colors 只包含字母 'A' 和 'B'

题解

滑动窗口

题目其实特别简单,因为题目要求要连续的三个 A 或者连续的三个 B,虽然题目说每次的选择都会是最优解,但是其实无论 Alice 和 Bob 怎么做出选择都不会影响最后的结果

image.png

如上图,Bob 在删除 B 的时候最少还会留下两个 B 并不会影响到 Alice 移除 A ,同理,Alice 操作也不会影响到 Bob。

所以其实两个人的操作互不影响,那也就谈不上什么博弈,这道题的难度其实应该是很低的,我们只要去循环字符串,判断分别有多少个 A,B 满足 Alice 和 Bob 的删除条件,然后对比一下两个数的大小,就能够知道谁会胜利了。

/**
 * @param {string} colors
 * @return {boolean}
 */
 var winnerOfGame = function(colors) {
    let A = 0
    let B = 0
    for(let i=0;i<colors.length-2;i++){
        if(colors[i]+colors[i+1]+colors[i+2] == 'AAA'){
            A++
        }
        if(colors[i]+colors[i+1]+colors[i+2] == 'BBB'){
            B++
        }
    }
    if(A>B){
        return true
    }
    return false
};

image.png

优化

上面的执行效率并不是特别的理想,稍微做一下代码的优化。

我们新建一个变量用于存放当前 A 或者 B 出现的次数,当它大于等于 3 的时候,说明接下去每一次出现都是 Alice 或 Bob 能够移出的次数,我们可以用这个数来做一个判断,这样就不用做字符串拼串,能节省很多时间。

/**
 * @param {string} colors
 * @return {boolean}
 */
var winnerOfGame = function(colors) {
    let A = 0;
    let B = 0;
    let cur = '';
    let cnt = 0;
    for (let i = 0; i < colors.length; i++) {
        const ch = colors[i];
        if (ch !== cur) {
            cur = ch;
            cnt = 1;
        } else {
            cnt += 1;
            if (cnt >= 3) {
                if(cur == 'A'){
                    A++
                }
                if(cur == 'B'){
                    B++
                }
            }
        }
    }            
    return A > B;
};

image.png