最长的字母子字符串 - 从哪里开始

时间:2018-05-16 08:58:00

标签: python algorithm sorting

我正在研究流行的麻省理工学院课程中“最长的字母表子串”问题。我已经阅读了很多有关如何编写代码的信息,但我真的很难在概念上实现飞跃。在它之前的手指练习并不太难。我想知道是否有人知道那里的任何材料会真正打破解决问题的问题。我试过拿出笔和纸,我只是迷路了。我看到人们使用各种类型的“计数器”,或者包含“迄今为止最长的子串”的字符串,当我看到别人的解决方案时,我可以理解他们对代码做了什么,但是如果我试图合成我自己的东西它只是不点击。

我甚至从课程中休息了一下并尝试通过其他书籍学习,但我一直回到这个问题,觉得我需要突破它。我想我正在努力的是从了解一些Python语法和工具到实际使用这些工具有效地解决问题或“计算”。

在任何人指出我之前,我都知道旨在帮助的课程材料。我已经看过一些视频,其中一个TA有些帮助,但他并没有真正打破这一点。我觉得我需要将它与某人或类似的人配对...坐在白板前面让别人一步一步地走我,回答我会遇到的每一个愚蠢的问题。

供参考,问题如下:

  

假设s是一个小写字符串。

     

编写一个程序,打印s中最长的子字符串,其中字母按字母顺序出现。例如,如果s ='azcbobobegghakl',那么您的程序应该打印

     

按字母顺序排列的最长子字符串是:beggh

     

在tie的情况下,打印第一个子字符串。例如,如果s ='abcbcd',那么您的程序应该打印

     

按字母顺序排列的最长子字符串是:abc

我知道发布代码很有帮助,但我没有其他任何东西在SO上,因为,好吧,这就是我在IDE中一直在玩的东西,看看我是否能理解正在发生的事情。同样,不寻找代码片段 - 更多的阅读或资源将扩展在此问题中使用的逻辑。我将发布我所拥有的内容,但它并不完整,而且在我开始感到困惑之前就已经到了。

s = 'azcbobobegghakl'

current = s[0]
longest = s[0]

for letter in range(0, len(s) -1):
    if s[letter + 1] >= s[letter]:
        current.append(s[letter + 1])
        if len(current) > len(longest):
            longest = current
        else:
            current = 

很抱歉格式错误,对此仍然是新手。我真的很沮丧这个问题。

5 个答案:

答案 0 :(得分:1)

你的例子几乎就在那里,只需要稍微调整一下

s = 'azcbobobegghakl'

longest = [s[0],]  # make them lists so we can manipulate them (unlike strings)
current = [s[0],]

for letter in range(0, len(s) -1):
    if s[letter + 1] >= s[letter]:
        current.append(s[letter + 1])
        if len(current) > len(longest):
            longest = current
    else:
        current = [s[letter+1],]  # reset current if we break an alphabetical chain

longest_string = ''.join(longest)  # turn out list back into a string

longest_string的输出:

'beegh'

答案 1 :(得分:1)

通常,从输入创建所有可能性的列表更容易,然后根据所需的附加逻辑过滤结果。例如,当找到最长的子串时,可以找到输入的所有子串,然后只保留有效序列的元素:

def is_valid(d):
  return all(d[i] <= d[i+1] for i in range(len(d)-1))

def longest_substring(s):
  substrings = list(filter(is_valid, [s[i:b] for i in range(len(s)) for b in range(len(s))]))
  max_length = len(max(substrings, key=len)) #this finds the length length of the longest valid substring, to be used if a tie is discovered
  return [i for i in substrings if len(i) == max_length][0]

l = [['abcbcd', 'abc'], ['azcbobobegghakl', 'beggh']]
for a, b in l:
  assert longest_substring(a) == b

print('all tests passed')

输出:

all tests passed

答案 2 :(得分:1)

如果您正在努力解决这个问题背后的概念和逻辑,我建议您稍微退一步,然后通过更简单的编码教程和互动练习。您可能还喜欢尝试使用JavaScript,从一开始就可以更轻松地获得创意,构建可以在浏览器中立即与之交互的片段和/或网页。然后,当你获得更多有趣的编码词汇时,它的算法部分看起来会更加熟悉和自然。我也认为让自己的创造力和想象力引导你可以成为一个非常强大的学习过程。

让我们忘记当前的字母部分。想象一下,我们有一个字母,我们一次拉出一个字母而不知道接下来是哪一个,我们必须连续记录最长的R秒。你会怎么做?让我们尝试用单词描述过程,然后是伪代码。

我们将保留一个容器,用于我们目前为止看到的最长跑,另一个用于检查当前跑步。我们拉字母,直到我们连续两个R s,我们把它放在“当前”容器中。下一个字母不是R,这意味着我们的运行结束了。 “最长 - 最远”的运行是空的,所以我们将“当前”容器倒入其中并继续运行。接下来的四个字母不是R s所以我们只是忽略它们。然后我们得到一个R,我们将其放入“当前”,然后放入H。我们的比赛再次结束,但是这次我们在“当前”中的R比我们在“最长 - 最远”中已经有的那么少,所以我们保留这些并且清空“当前”。

我们收到ABC,然后是5个R,我们将其放入“当前”容器中一个人。我们的包现在包含最后一个字母T。我们看到我们的运行再次结束,并且“当前”容器具有的不仅仅是“最长的”容器,因此我们倒出“最长”并用“当前”中的五个R替换其内容。就是这样,我们发现了包中最长的R s。 (如果我们有更多的运行,每次结束时我们都会选择是否替换“最长的东西”。)

在伪代码中:

// Initialise
current <- nothing
longest <- nothing

for letter in bag:
  if letter == 'R':
    add 'R' to current
  else:
    if there are more letters
    in current than longest:
      empty longest and pour
      in letters from current
    otherwise:
      empty current to get ready
      for the next possible run

现在按字母顺序排列的条款稍微复杂一点。我们需要跟踪最近放在“当前”中的字母,并且为了继续运行,它没有看到另一个相同的字母。相反,下一个字母必须比我们放在当前的最后一个字母“更大”(按字典顺序排列);否则运行结束,我们执行数量检查“最长 - 迄今为止。”

答案 3 :(得分:1)

对我来说,处理实现复杂性的一种方法是编写一些单元测试:在某些时候,如果我无法从“读取代码”中弄清楚什么是错误的,和/或缺少哪些部分,我喜欢编写单元测试,这是一种解决问题的“正交”方法(而不是思考“我该如何解决这个问题?”我问自己“我应该编写哪些测试来验证它是否正常?”)。

然后,通过运行测试,我可以观察实现的行为,并尝试“逐个”解决问题,即集中精力使下一个单元测试通过。

这也是“在更容易推理的小问题中解决大问题”的一种方式。

答案 4 :(得分:0)

s = 'azcbobobeggh'

ls = [] #create a new empty list

for i in range(len(s) - 1): # iterate s from index 0 to index -2
    if s[i] <= s[i+1]: # compare the letters
        ls.append(s[i]) # after comparing them, append them to the new list
    else:
        ls.append(s[i])
        ls.append('mark') # place a 'mark' to separate them into chunks by order
ls.append(s[-1]) # get back the index -1 that missed by the loop

# at this point here ls:
# ['a', 'z', 'mark', 'c', 'mark', 'b', 'o', 'mark', 'b', 'o', 'mark', 'b', 'e', 'g', 'g', 'h']

ls = str(''.join(ls)) # 'azmarkcmarkbomarkbomarkbeggh'
ls = ls.split('mark') # ['az', 'c', 'bo', 'bo', 'beggh']
res = max(ls, key=len) # now just find the longest string in the list

print('Longest substring in alphabetical order is: ' + res)

# Longest substring in alphabetical order is: beggh