【问题标题】:Find the longest substring with contiguous characters, where the string may be jumbled查找具有连续字符的最长子字符串,其中字符串可能混乱
【发布时间】:2023-04-05 20:56:01
【问题描述】:

给定一个字符串,找到最长的子字符串,其字符是连续的(即它们是连续的字母)但可能是混乱的(即乱序)。例如:
输入:"owadcbjkl"
输出:"adcb"
我们认为adcb 与它形成abcd 一样连续。

(这是一道面试题。)

我有一个想法,使用 2 个条件运行一个 while 循环,一个使用 Python 的 ord 检查连续字符,另一个条件是找到最小值和最大值,并检查以下所有字符是否都在此范围内。

有没有什么方法可以在运行时间复杂度低的情况下解决这个问题?我能做到的最好是 O(N^2) 其中 N 是输入字符串的长度,ord() 似乎是一个缓慢的操作。

【问题讨论】:

  • 这个问题太冗长了:试着把你的算法写成类似 Python 的格式(伪代码),这样我们就能更好地理解它。
  • 这种问题在这里是题外话。您应该通过codereview.stackexchange.com 询问这个问题
  • 请详细解释您的问题中定义有效子字符串的内容。你说adcb 是有效的,adc 也是有效的吗?
  • 简单的O(n*m*m) 解决方案可以基于最长子字符串不超过m 的事实,其中m 是字母大小。如果m 是固定的,例如m == 26,那么它是一个线性时间(虽然无效)的解决方案。如果m 不固定,则this question might be related
  • @OcasoProtal 这个问题完全是关于Stack Overflow 的主题,因为它是关于实现a software algorithm。在Code Review 上将是题外话,这只是关于审查工作代码;我很困惑为什么你会建议它。关于算法本身的问题将在 Computer Science 上讨论,但不会在 Python 中实现:这绝对属于 Stack Overflow

标签: python string algorithm


【解决方案1】:

如果子字符串被定义为''.join(sorted(substr)) in alphabet 那么:

  • 子字符串中没有重复项,因此 最长的子串小于(或等于)字母表的大小

  • (ord(max(substr)) - ord(min(substr)) + 1) == len(substr),其中 ord() 返回字母表中的位置(+/- 常量)(内置 ord() 可用于小写 ascii 字母)

这是O(n*m*m)-time,O(m)-space 解决方案,其中nlen(input_string)mlen(alphabet)

from itertools import count

def longest_substr(input_string):
    maxsubstr = input_string[0:0] # empty slice (to accept subclasses of str)
    for start in range(len(input_string)): # O(n)
        for end in count(start + len(maxsubstr) + 1): # O(m)
            substr = input_string[start:end] # O(m)
            if len(set(substr)) != (end - start): # found duplicates or EOS
                break
            if (ord(max(substr)) - ord(min(substr)) + 1) == len(substr):
                maxsubstr = substr
    return maxsubstr

例子:

print(longest_substr("owadcbjkl"))
# -> adcb

【讨论】:

  • 谢谢我只有一个问题,为什么字符串切片 O(m) 我假设字符串切片就像 python 中的数组索引一样快。已知 char python 的长度应该很容易找到最后一个索引吧?还是一直遍历寻找切片的结尾?
  • 另外,如果我们使用额外的数据结构,我们可以降低时间复杂度吗?
  • @Sandy:在 CPython 中对字符串进行切片会返回一个 copy。要复制 m 字符,您需要 O(m) 时间和 O(m) 空间。 buffer()memoryview() 可以用来避免复制,但 setmaxmin 是 O(m) 时间,因此不会提高时间复杂度。
  • @Sandy:如果你保持min[startpos] 存储从startpos 开始的最小值直到当前位置,你可能会得到O(n*m),并在重复时使用它来重置当前substr 的起始位置检测到(您可以使用大小为len(alphabet)seen 列表来保持重复所在的位置)。我还没想好。对于固定的m (len(alphabet)),它只是提高了常数因子并且不会改变时间复杂度。我不确定关于n (len(input_string)) 的次线性时间性能是否可行。
  • 如果我们使用字符数组而不是实际字符串本身会怎样,像你说的那样在内部循环中保持最小值和最大值,然后每次取 max(prev_max,new_charc) = O(1 ) 和 min(prev_min,new_charac) = O(1).. 那么我们可以实现 O(N*M) 对吗?你认为我们可以把这个降低吗?
猜你喜欢
  • 2020-06-28
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-21
  • 1970-01-01
相关资源
最近更新 更多