我的博客

leetcode weekly contest 159 周赛 5232. 替换子串得到平衡字符串 1234. Replace the Substring for Balanced String

目录
  1. 解答

有一个只含有 'Q', 'W', 'E', 'R' 四种字符,且长度为 n 的字符串。

假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。

给你一个这样的字符串 s,请通过「替换子串」的方式,使原字符串 s 变成一个「平衡字符串」。

你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。

请返回待替换子串的最小可能长度。

如果原字符串自身就是一个平衡字符串,则返回 0

示例 1:

1
2
3
输入:s = "QWER"
输出:0
解释:s 已经是平衡的了。

示例 2:

1
2
3
输入:s = "QQWE"
输出:1
解释:我们需要把一个 'Q' 替换成 'R',这样得到的 "RQWE" (或 "QRWE") 是平衡的。

示例 3:

1
2
3
输入:s = "QQQW"
输出:2
解释:我们可以把前面的 "QQ" 替换成 "ER"。

示例 4:

1
2
3
输入:s = "QQQQ"
输出:3
解释:我们可以替换后 3 个 'Q',使 s = "QWER"。

提示:

  • 1 <= s.length <= 10^5
  • s.length4 的倍数
  • s 中只含有 'Q', 'W', 'E', 'R' 四种字符

解答

动态规划。

先统计原字符串中,四个字母的个数。题目的要求可以转化为让每个字母的个数都是 length // 4 个。那么我们只看数量超过这个目标个数的字母。

我们想到的子串就是要包含这些数量超标字母,而且个数不小于他们超标数量。

我下面用 d 数组表示每个字母超标个数,有的为负数,说明不超标。

然后 dp[i] 表示,从 i 个字母开头(包含)的字串的最短长度。

dp[0] 好求,就是从头往后计算个字母个数,存到 d2 里。直到 d2 每个元素大于等于 d 的相应元素。

然后从 1 到 len(s) 求 dp。dp[i] 的长度一定大于等于 dp[i-1] - 1。我们可以直接在 d2 的基础上减去 s[i-1] 这个字母,就是 dp[i] 初始情况下个字母的个数了。如果不满足那么就按照 dp[i-1] - 1 的长度为起始,继续往下遍历。如果有不满足的情况,就结束 dp 数组的求解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution:
def balancedString(self, s: str) -> int:
c = {'Q': 0, 'W': 1, 'E': 2, 'R': 3}
d = [0 for i in range(4)]
for ch in s:
d[c[ch]] += 1
t = len(s) // 4
for i in range(len(d)): d[i] -= t
dp = [0 for i in range(len(s))]
d2 = [0 for i in range(4)]
i = 0
while i < len(s):
if d2[0] >= d[0] and d2[1] >= d[1] and d2[2] >= d[2] and d2[3] >= d[3]:
break
else:
d2[c[s[i]]] += 1
i += 1
if i < 2: return i
dp[0] = i
minv = i
for i in range(1, len(s)):
d2[c[s[i-1]]] -= 1
j = i + dp[i-1] - 1
flag = False
while j < len(s):
if d2[0]>=d[0] and d2[1] >= d[1] and d2[2] >= d[2] and d2[3] >= d[3]:
flag = True
break
else:
d2[c[s[j]]] += 1
j += 1
if not flag and not(d2[0]>=d[0] and d2[1] >= d[1] and d2[2] >= d[2] and d2[3] >= d[3]):
break
dp[i] = j - i
minv = min(minv, dp[i])
return minv

评论无需登录,可以匿名,欢迎评论!