为什么我的for循环不起作用?(Python)

迪伊

是的,这是家庭作业。我只是想了解为什么这似乎行不通。

我正在尝试按字母顺序查找字符串中最长的子字符串。我列出了一个随机字母列表,并说长度为19。在运行代码时,它会打印出索引0到17。(我知道发生这种情况是因为我从范围中减去1)但是,当我将其省略时- 1,它告诉我“字符串索引超出范围”。为什么会这样呢?

s = 'cntniymrmbhfinjttbiuqhib'
sub = ''
longest = []

for i in range(len(s) - 1):
    if s[i] <= s[i+1]:
        sub += s[i]
        longest.append(sub)
    elif s[i-1] <= s[i]:
        sub += s[i]
        longest.append(sub)
        sub = ' '
    else:
        sub = ' '
print(longest)
print ('Longest substring in alphabetical order is: ' + max(longest, key=len))

我也尝试了其他一些方法

如果我只是说:

for i in s:

它将引发错误,并说“字符串索引必须是整数,而不是str。” 这似乎是一种遍历字符串的简单得多的方法,但是我将如何以这种方式比较各个字母呢?

顺便说一下,这是Python 2.7。

编辑:我确定我的if / elif语句可以改进,但这是我想到的第一件事。如有需要,我可以稍后再谈。

Thebjorn

我确信我的if / elif语句可以改进,但这是我首先想到的。如有需要,我可以稍后再谈。

@ or1426的解决方案创建当前最长排序序列的列表,并将其复制到longest发现更长序列的位置。每当找到更长的序列时,都会创建一个新列表,并将其添加到每个字符的列表中。在Python中,这实际上非常快,但请参见下文。

@Deej的解决方案将当前最长的排序序列保留在字符串变量中,并且每次找到更长的子字符串(即使是当前序列的延续)时,该子字符串也会保存到列表中。该列表最终具有原始字符串的所有已排序子字符串,并且通过调用来找到最长的子字符串max

这是一个更快的解决方案,它仅跟踪当前最大序列的索引,并且仅在找到未排序顺序的字符时才将更改最长。

def bjorn4(s):
    # we start out with s[0] being the longest sorted substring (LSS)
    longest = (0, 1)    # the slice-indices of the longest sorted substring
    longlen = 1         # the length of longest
    cur_start = 0       # the slice-indices of the *current* LSS
    cur_stop = 1

    for ch in s[1:]:       # skip the first ch since we handled it above
        end = cur_stop-1   # cur_stop is a slice index, subtract one to get the last ch in the LSS
        if ch >= s[end]:   # if ch >= then we're still in sorted order..
            cur_stop += 1  # just extend the current LSS by one
        else:
            # we found a ch that is not in sorted order
            if longlen < (cur_stop-cur_start):
                # if the current LSS is longer than longest, then..
                longest = (cur_start, cur_stop)    # store current in longest
                longlen = longest[1] - longest[0]  # precompute longlen

            # since we can't add ch to the current LSS we must create a new current around ch
            cur_start, cur_stop = cur_stop, cur_stop+1

    # if the LSS is at the end, then we'll not enter the else part above, so
    # check for it after the for loop
    if longlen < (cur_stop - cur_start):
        longest = (cur_start, cur_stop)

    return s[longest[0]:longest[1]]

快多少?它的速度几乎是orl1426的两倍,是deej的三倍。与往常一样,这取决于您的输入。存在的排序子字符串块越多,上述算法与其他算法相比将越快。例如,在长度为100000的输入字符串中,包含交替的100个随机字符和100个有序字符,我得到:

bjorn4: 2.4350001812
or1426: 3.84699988365
deej  : 7.13800001144

如果我将其更改为交替使用1000个随机字符和1000个排序的字符,那么我得到:

bjorn4: 23.129999876
or1426: 38.8380000591
deej  : MemoryError

更新:这是我的算法的进一步优化版本,带有比较代码:

import random, string
from itertools import izip_longest
import timeit

def _randstr(n):
    ls = []
    for i in range(n):
        ls.append(random.choice(string.lowercase))
    return ''.join(ls)

def _sortstr(n):
    return ''.join(sorted(_randstr(n)))

def badstr(nish):
    res = ""
    for i in range(nish):
        res += _sortstr(i)
        if len(res) >= nish:
            break
    return res

def achampion(s):
    start = end = longest = 0
    best = ""
    for c1, c2 in izip_longest(s, s[1:]):
        end += 1
        if c2 and c1 <= c2:
            continue
        if (end-start) > longest:
            longest = end - start
            best = s[start:end]
        start = end
    return best

def bjorn(s):
    cur_start = 0
    cur_stop = 1
    long_start = cur_start
    long_end = cur_stop

    for ch in s[1:]:      
        if ch < s[cur_stop-1]:
            if (long_end-long_start) < (cur_stop-cur_start):
                long_start = cur_start
                long_end = cur_stop
            cur_start = cur_stop
        cur_stop += 1

    if (long_end-long_start) < (cur_stop-cur_start):
        return s[cur_start:cur_stop]
    return s[long_start:long_end]


def or1426(s):
    longest = [s[0]]
    current = [s[0]]
    for char in s[1:]:
        if char >= current[-1]: # current[-1] == current[len(current)-1]
            current.append(char)
        else:            
            current=[char]
        if len(longest) < len(current):
            longest = current
    return ''.join(longest)

if __name__ == "__main__":
    print 'achampion:', round(min(timeit.Timer(
        "achampion(rstr)",
        setup="gc.enable();from __main__ import achampion, badstr; rstr=badstr(30000)"
    ).repeat(15, 50)), 3)

    print 'bjorn:', round(min(timeit.Timer(
        "bjorn(rstr)",
        setup="gc.enable();from __main__ import bjorn, badstr; rstr=badstr(30000)"
    ).repeat(15, 50)), 3)

    print 'or1426:', round(min(timeit.Timer(
        "or1426(rstr)",
        setup="gc.enable();from __main__ import or1426, badstr; rstr=badstr(30000)"
    ).repeat(15, 50)), 3)

输出:

achampion: 0.274
bjorn: 0.253
or1426: 0.486

将数据更改为随机数据:

achampion: 0.350
bjorn: 0.337
or1426: 0.565

并排序:

achampion: 0.262
bjorn: 0.245
or1426: 0.503

“不,不,它还没死,它正在休息”

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

我是 python 新手,我想知道为什么这个 while 循环不起作用

为什么在我的jQuery循环中返回不起作用?

为什么我的循环在GoogleSheets上不起作用?

为什么我的foreach循环不起作用?

为什么我对ls输出的循环不起作用?

为什么 strptime() 在我的 for 循环中不起作用?

为什么我的张量流而循环不起作用

我不明白为什么for循环不起作用

为什么我的PERFORM循环不起作用?

为什么我的While循环不起作用?

为什么我的 FOR 循环在这里不起作用?

为什么我的 for 循环不起作用?阶乘程序

为什么我的 do-while 循环不起作用?

为什么我的函数在循环中不起作用?

Python:为什么我的写入功能在while循环中不起作用?

为什么嵌套的 for 循环在 Python 中不起作用?

为什么这个内联循环在 python 中不起作用?

为什么这个 Python“循环代码”不起作用?

为什么这个for()循环不起作用?

为什么while循环不起作用?

为什么我的Python PIL导入不起作用?

为什么我的“else”语句在 python 中不起作用?

为什么我的 Python 3 代码不起作用?

为什么replace()在我的Python函数中不起作用?

为什么我的 IF 语句在 python 上不起作用?

Python 和 BeautifulSoup:为什么我的 if 条件不起作用

为什么我的def函数在Python中不起作用?

Python:为什么我的类方法不起作用?

Python-Beautifulsoup | 为什么我的find()不起作用?