📅  最后修改于: 2023-12-03 15:27:52.143000             🧑  作者: Mango
给定一个字符串s,只包含字符X和Y。现在需要求出在s字符串的末尾添加字符X或Y,使得最终字符串满足从头到尾的字符是严格递增的,即不会出现 XXY 或 YYX 这样的情况。
请编写一个函数接受一个字符串s作为参数,返回添加字符的最小数量。
如示例:输入 s = "YXYXXXY",输出2,因为在结尾添加两个X,即"YXYXXXYXX",则从头到尾的字符严格递增。
由于只允许在字符串末尾添加字符,所以可以使用贪心算法求解。
从前往后扫描字符串s,记录当前需要添加的字符类型(即X或Y)和该类型字符的数量,如果下一个字符比当前字符小,则需要在结尾添加一个与当前字符不同的字符。此时根据贪心思想,应该尽可能添加当前类型字符的反向类型,即如果当前字符为X,则应该在结尾添加Y;如果当前字符为Y,则应该在结尾添加X。同时,更新当前需要添加的字符类型和数量,直到扫描完整个字符串。
由于仅需记录字符类型和数量,时间复杂度为O(n),是一种快速且简单的解法。
另一种经典的算法是动态规划,使用一个二维数组dp表示将s字符串前i个字符转换成字符递增需要添加的最小字符数。其中,dp[i][0]表示在s[i-1]位置添加X的最小字符数,dp[i][1]表示在s[i-1]位置添加Y的最小字符数。
对于每个字符s[i-1],可以判断它是否比前一个字符s[i-2]小,如果小,则需要添加一个不同的类型字符。则有:
最终的结果就是dp[n][0]和dp[n][1]的较小值,其中n为字符串s的长度。
这种方法的时间复杂度为O(n),需要一个二维数组存储中间结果,空间复杂度为O(n)。
def append_string(s: str) -> int:
if not s:
return 0
cnt, pre = 0, ''
for i in range(len(s)):
if pre and s[i] < pre:
cnt += 1
pre = 'Y' if pre == 'X' else 'X'
pre_cnt = s[:i+1].count(pre)
oppo_cnt = i+1-pre_cnt
if pre_cnt <= oppo_cnt:
pre = 'X'
else:
pre = 'Y'
return cnt
def append_string(s: str) -> int:
if not s:
return 0
dp = [[0, 0] for _ in range(len(s)+1)]
for i in range(1, len(s)+1):
if s[i-1] < s[i-2]:
dp[i][0] = dp[i-1][1]+1
dp[i][1] = dp[i-1][1]
else:
dp[i][0] = dp[i-1][0]
dp[i][1] = dp[i-1][0]+1
return min(dp[-1])