【问题标题】:What is a faster version of this code instead of the double for-loop (python)?什么是此代码的更快版本而不是双 for 循环(python)?
【发布时间】:2018-10-25 17:34:21
【问题描述】:

当我将这段代码提交到一个可以纠正它的网站(来自我的大学)时,它对于它的标准来说太长了。 代码如下:

def pangram(String):
    import string
    alfabet = list(string.ascii_lowercase)
    interpunctie = string.punctuation + "’" + "123456789"
    String = String.lower()
    string_1 = ""
    for char in String:                    
        if not char in interpunctie:
            string_1 += char
    string_1 = string_1.replace(" ", "")    
    List = list(string_1)
    List.sort()                            
    list_2 = []
    for index, char in enumerate(List):     
        if not List[index] == 0:
            if not (char == List[index - 1]):
                list_2.append(char)
    return list_2 == alfabet              

def venster(tekst):
    pangram_gevonden = False
    if pangram(tekst) == False: 
        return None
    for lengte in range(26, len(tekst)):
        if pangram_gevonden == True:
            break
        for n in range(0, len(tekst) - lengte):
            if pangram(tekst[n:lengte+n]):
                kortste_pangram = tekst[n:lengte+n]
                pangram_gevonden = True
                break
    return kortste_pangram

所以第一个函数(pangram)很好,它可以确定给定字符串是否是 pangram:它至少包含一次字母表中的所有字母。

第二个函数检查字符串(通常是较长的 tekst)是否是 pangram,如果是,则返回该 tekst 中可能最短的 pangram(即使这不是正确的英语)。如果有两个长度相同的pangram:返回最左边的一个。

对于第二个函数,我使用了双 for 循环:第一个确定要检查的字符串的长度 (26 - len(string)),第二个使用这个长度在每个可能的点遍历字符串检查它是否是一个pangram。一旦找到最短(也是最左边)的 pangram,它就会跳出两个 for 循环。

但是,这(显然)仍然需要很长时间。所以我想知道是否有人知道处理第二个功能的更快方法。它不一定必须带有 for 循环。

提前致谢

卢卡斯

【问题讨论】:

  • 代码格式化的按钮是编辑器中的{}。您已将其全部格式化为引号
  • 欢迎来到 StackOverflow。请按照您创建此帐户时的建议阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。对我来说主要的问题是你已经包含了 很多 多余的代码,并且在你想要的改进方面没有显示出任何进展。
  • 我也试过运行你的代码:它似乎没有产生任何输出。
  • 感谢您的帮助。我会考虑编辑我的帖子并尝试删除尽可能多的不必要的代码;
  • 如果在字符串中没有找到 pangram,则代码返回 None。也许这就是你的意思?当我运行它时,它确实正确地给出了它应该给出的字符串。

标签: python algorithm


【解决方案1】:

创建地图{letter; int}activecount 计数器。
制作两个索引leftright,设置为0。

移动right索引。
如果l=s[right] 是字母,则增加映射键l 的值。
如果值变为非零 - 增加 activecount.
继续直到activecount 达到 26

现在移动 left 索引。
如果l=s[left] 是字母,则减少映射键l 的值。
如果值变为零 - 减少 activecount 并停止。

再次开始移动right 索引,依此类推。

leftright 之间的最小差异而
activecount==26 对应于最短的pangram。

算法是线性的。

仅包含字母“abcd”中小写字母的字符串示例代码。返回包含来自abcd 的所有字母的最短子字符串的长度。不检查有效字符,未经彻底测试。

import string
def findpangram(s):
    alfabet = list(string.ascii_lowercase)
    map = dict(zip(alfabet, [0]*len(alfabet)))
    left = 0
    right = 0
    ac = 0
    minlen = 100000

    while left < len(s):

        while right < len(s):
            l = s[right]
            c = map[l]
            map[l] = c + 1
            right += 1
            if c==0:
                ac+=1
                if ac == 4:
                    break
        if ac < 4:
            break
        if right - left < minlen:
            minlen = right - left

        while left < right:
            l = s[left]
            c = map[l]
            map[l] = c - 1
            left += 1
            if c==1:
                ac-=1
                break

        if right - left + 2 < minlen:
            minlen = right - left + 1
    return minlen

print(findpangram("acacdbcca"))

【讨论】:

  • 也许我忘了补充,虽然我只是一个初级程序员,所以我不知道地图是什么或它是如何工作的。您介意将其中的一些传输到代码中吗?
  • map 是 dict - 键值对 - Python 中的内置数据结构。我会快速编写代码。
  • 非常感谢!顺便说一句,变量的名称可以是任何名称,它们不必与我的代码相对应。
  • 是的,当然,我并不是要让自己变得容易。只是我只编程了几个星期。我读了一本书,现在正在学习列表和元组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-26
  • 2014-09-22
  • 2011-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
相关资源
最近更新 更多