派派的刷题之旅(一) | 豆包MarsCode AI 刷题

43 阅读3分钟

最小替换子串长度

问题描述

小R对字符串的子串非常感兴趣,特别是关于所有不同的子串。他有一个字符串s,想知道其中第k小的不同子串是什么。小R希望你能帮他找到答案。如果第k小的子串不存在,则返回NO ANSWER

例如,给定字符串s = "aab",我们可以列出所有不同的子串,并按字典序排序。小R想知道排在第k小的子串是什么。

测试样例

样例1:

输入:s = "aab",k = 4
输出:'ab'

样例2:

输入:s = "abc",k = 6
输出:'c'

样例3:

输入:s = "banana",k = 10
输出:'banan'

思路解析

  1. 生成所有子串:我们需要遍历字符串 s,生成所有可能的子串。
  2. 去重:由于子串可能重复,我们需要使用集合(set)来存储子串,以确保所有子串都是唯一的。
  3. 排序:将集合中的子串按字典序排序。
  4. 查找第 k 小的子串:从排序后的子串列表中找到第 k 小的子串。

解题代码

def solution(s: str, k: int) -> str:
    # 1. 生成所有子串并存储在集合中
    substrings = set()
    for i in range(len(s)):
        for j in range(i + 1, len(s) + 1):
            substrings.add(s[i:j])
    
    # 2. 将子串按字典序排序
    sorted_substrings = sorted(substrings)
    
    # 3. 查找第 k 小的子串
    if k <= len(sorted_substrings):
        return sorted_substrings[k - 1]
    else:
        return "NO ANSWER"

代码模块详解

  1. 生成所有子串

    • 使用两个嵌套的循环来生成所有可能的子串。外层循环控制子串的起始位置,内层循环控制子串的结束位置。
    • 将生成的子串添加到集合 substrings 中,以确保所有子串都是唯一的。
  2. 排序

    • 使用 sorted() 函数对集合中的子串按字典序排序。
  3. 查找第 k 小的子串

    • 检查 k 是否在排序后的子串列表的长度范围内。如果是,返回第 k 小的子串;否则返回 "NO ANSWER"

复杂度分析

时间复杂度分析

  1. 生成所有子串

    • 外层循环 for i in range(len(s)) 运行 n 次(n 是字符串 s 的长度)。
    • 内层循环 for j in range(i + 1, len(s) + 1) 运行 n - i 次。
    • 因此,生成所有子串的时间复杂度为 O(n^2),因为总共有 n + (n-1) + (n-2) + ... + 1 个子串,这是一个等差数列求和,结果是 O(n^2)
  2. 去重

    • 使用集合 set 来存储子串,插入操作的时间复杂度是 O(1)
    • 因此,去重的时间复杂度也是 O(n^2)
  3. 排序

    • 假设生成的不同子串数量为 mm 最大为 n(n+1)/2),排序的时间复杂度为 O(m log m)
    • 在最坏情况下,m 接近 n^2,所以排序的时间复杂度为 O(n^2 log n)
  4. 查找第 k 小的子串

    • 查找操作的时间复杂度是 O(1)

综上所述,总的时间复杂度为 O(n^2) + O(n^2) + O(n^2 log n) = O(n^2 log n)

空间复杂度分析

  1. 存储所有子串

    • 使用集合 set 存储所有不同的子串,最坏情况下需要存储 n(n+1)/2 个子串,因此空间复杂度为 O(n^2)
  2. 排序后的子串列表

    • 排序后的子串列表也需要存储 m 个子串,最坏情况下 m 接近 n^2,因此空间复杂度为 O(n^2)

综上所述,总的空间复杂度为 O(n^2)

总结

  • 时间复杂度O(n^2 log n)
  • 空间复杂度O(n^2)