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的「相同连续字符」,并记录可操作次数A
和B
,A>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
};