284 模板串匹配问题| 豆包MarsCode AI刷题

41 阅读4分钟

问题描述

小U有一个特殊的“模板串”,这个串由数字字符和 '?' 组成。她可以通过将 '?' 替换成数字字符,来构造出多个正整数。不过有一个重要的限制条件:匹配出来的正整数不能有前导零。现在,小U想知道,按照字典序排列后,第 k 小的匹配数是多少?如果没有满足条件的第 k 小数,则返回 -1。

解题思路

通过分析题目,我们可以知道的是对于一个模板串,匹配出来的正整数不能有前导零。所以如果他的第一位是?,那么只能是从1开始,如果模板串本身就有前导零,那么就意味着直接没有满足条件的数,返回-1。而按字典序排序意味著符合数字的大小关系。那么我们只需要数数就可以了。我们将提取出来,有几个就是几位数,将其替换成可以有前导零的k-1,就可以了。当然,如果有?排在模板串的第一位,那么就应该以最大位为1其他为0开始计数,例如假设模板串有4个问号,那么应该从1000开始计数。

代码实现

首先是对模板串的第一位进行确认,如果是零,那么直接返回'-1',如果是'?',记录下标,并且值从1开始。

    result = []
    if s[0] == '0':
        return '-1'
    elif s[0] == '?':
        result.append([0,'1'])

接着遍历模板串,将所有的'?'的位置记录,并从零开始计数。

    for i, e in enumerate(s):
        if i == 0:
            continue
        elif e == '?':
            result.append([i, '0'])

检查数组中是否有值,如果没有那么模板串中没有'?'可用于替换,那么可以返回'-1'

    if len(result) <= 0:
        return '-1'


准备一个空串,将数组中的值提取出来转化成整型,好用于直接计数,然后计数就是了

    num = ''
    for i in result:
        num += i[1]
    num = str(int(num)+k-1)

再做一些判断即可,如果计数完成后,长度比数组长度长说明要计的数越界了,返回'-1'而如果记得数无法满足长度要求,那么我们需要将前导零补回去,因为之前将其转化成整型,有前导零的会被消除,其实主要是可能模板串的第一位是'?'导致可能不是从0开始,当然如果不想这样做,也可以在这一步判断一下是否模板串第一位是'?',然后对加上pow(10,len(result)-1),也是可以的,这表示最大位加一。然后将得到的数替换回去就可以了。

    if len(num) > len(result):
        return '-1'
    while len(num) < len(result):
        num = '0'+num
    s = list(s)
    for i in range(len(num)):
        s[result[i][0]] = num[i]

当然因为我这里是替换,所以返回时就会使用list将原来的字符串转化成列表。又因为题目是要求返回的是完整字符串型,所以要做点处理。

    return ''.join(s)

复杂度分析

时间复杂度

  • 对于 s 长度为 n,我们首先遍历一次字符串 s 来找到 '?' 的位置,时间复杂度为 O(n) 。
  • 然后,我们构造一个新的数字 num,这个过程的时间复杂度为 O(m) ,其中 m 是 '?' 的数量。
  • 数字加法操作和字符串长度调整的时间复杂度也是 O(m)。
  • 替换回原字符串的操作的时间复杂度是 O(m) 。
  • 最后,转换列表为字符串的操作时间复杂度是 O(n) 。

因此,整体时间复杂度为 O(n + m) ,其中 n 是原字符串的长度,m 是字符串中 '?' 的个数。

空间复杂度

  • 我们需要存储 result 列表,存储替换字符的位置。空间复杂度为 O(m) ,其中 m 是 '?' 的个数。
  • 另外,我们还需要存储数字字符串 num,其空间复杂度为 O(m) 。
  • 最后,字符串转换成列表 s 需要额外的空间,空间复杂度为 O(n) 。

因此,总的空间复杂度为 O(n + m) 。