如果相邻两个颜色均相同则删除当前颜色(2022-3-22)每日一练

2038. 如果相邻两个颜色均相同则删除当前颜色(2022-3-22)

总共有 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 。

提示:

  • 1 <= colors.length <= 10^5
  • colors 只包含字母 'A''B'

详细示例请到力扣查看(点击题目即可前往)

解题思路

原本是想的模拟,一看提示数据范围到了10^5,普通模拟的时间复杂度肯定大于O(n logn),因为每次删除操作都要去查找一遍字符串。(也就是两层遍历)(然后我试了一下,毫无疑问的超时了)

所以换个思路,像这种查找连续相同字符的,双指针是个不二之选。

这道题我们转化下思路:题目所说每次遵从「最优操作」,但其实没有最优,除了临界的两个字符,操作中间任意一个都可以;换句话说,给定colors之后,A和B的可操作次数就确定了,就像AAAAA只能删除3次,无论先删除那一个。那么这道题就变成了查找长度大于3的「相同连续字符」,并记录可操作次数ABA>B则Alice赢,反之Bob赢。

具体实现:

  • 两个指针,左右指针的字符一样时,右指针继续向后,直到发现不一样。

  • 判断两指针的距离是否大于等于3,不是的话就没有可操作的。

  • 是的话,就判断是那个字符,就给这个字符的可操作数,做一次累加。

  • 然后让左指针等于右指针,继续遍历就OK了

值得注意的的一点是要保证遍历玩之后左右指针指向一样,因为右边界可能会一直相等,导致无法进入判断。

var winnerOfGame = function(colors) {
    let A = 0, B = 0
    for(let l = 0, r = 0; r <= colors.length; r++){
        if(colors[l] == colors[r]) continue
        if(r-l >= 3 && colors[l] == 'A'){
            A += (r-l-2)
        } else if(r-l >= 3){
            B += (r-l-2)
        }
        l = r
    }
    if(A <= B)return false
    return true
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您解答这个问题。 地图染色问题是一个经典的图论问题,可以使用图的染色算法来解决。对于这个问题,可以使用回溯法来解决。 具体地,我们可以用一个数组colors来存储每个地图块的颜色。对于每一个地图块,我们可以依次尝试三种颜色,如果某一种颜色可以被涂色并且不与相邻地图块的颜色相同,则可以涂上这种颜色,然后递归到下一个地图块,继续进行涂色。 如果某一种颜色无法被涂色或者涂上这种颜色会与相邻地图块的颜色相同,则需要回溯到上一个地图块,尝试下一种颜色。 具体实现可以参考下面的代码: ```c #include <stdio.h> #include <stdbool.h> #define MAP_SIZE 5 #define COLOR_NUM 3 bool is_valid(int map[MAP_SIZE][MAP_SIZE], int colors[MAP_SIZE], int map_index, int color) { for (int i = 0; i < MAP_SIZE; i++) { if (map[map_index][i] && colors[i] == color) { return false; } } return true; } bool color_map(int map[MAP_SIZE][MAP_SIZE], int colors[MAP_SIZE], int map_index) { if (map_index == MAP_SIZE) { // 所有地图块都已经涂色完成 return true; } for (int color = 1; color <= COLOR_NUM; color++) { if (is_valid(map, colors, map_index, color)) { colors[map_index] = color; if (color_map(map, colors, map_index + 1)) { return true; } colors[map_index] = 0; // 回溯 } } return false; } int main() { int map[MAP_SIZE][MAP_SIZE] = { {0, 1, 1, 0, 0}, {1, 0, 1, 1, 1}, {1, 1, 0, 1, 0}, {0, 1, 1, 0, 1}, {0, 1, 0, 1, 0} }; int colors[MAP_SIZE] = {0}; if (color_map(map, colors, 0)) { printf("Solution found:\n"); for (int i = 0; i < MAP_SIZE; i++) { printf("Map %d: Color %d\n", i, colors[i]); } } else { printf("No solution found\n"); } return 0; } ``` 需要注意的是,在这个实现中,我们使用了一个二维数组map来表示地图,map[i][j]表示第i个地图块和第j个地图块是否相邻。同时,我们使用一个一维数组colors来存储每个地图块的颜色,其中0表示未涂色,1表示
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值