加快python嵌套循环

时间:2015-06-24 03:20:25

标签: python algorithm performance loops

这是我的代码。处理大字符串输入需要花费超过一分钟的时间。有什么办法可以解决这个问题

q=int(input())
x=input()
count=0
for i in range(q):
    for j in range(q):
        k= j+i+1
        if k<=q:
            u=x[i:k]
            if u[0]==u[-1] or len(u)==1:
                count+=1


print(count)

6 个答案:

答案 0 :(得分:1)

至少有两个问题:

1)你正在循环过多的值,其中你的k是> Q值。内环应该在一个取决于i

的范围内

2)所有切片的重点是什么(u = x [i:k])?为什么直接检查u [0]和u [-1]而不是x [i]和x [k-1]?另外 - 你可以通过对i和k进行算术来检查你的长度。那些切片是不必要的,可能是罪魁祸首。

无论如何 - 很有可能会有一种非常简单的方法可以做你想做的事情,完全避免嵌套循环。

答案 1 :(得分:1)

您不需要两个for循环来执行此操作,您只需累计计算重复的字符即可。这样你就可以在O(n)时间内找到结果,但会产生额外的O(n)空间。

q=int(input())
x=input()
from collections import defaultdict
d1 = defaultdict(int)
count = 0
for i in x:
    d1[i] += 1
    count += d1[i]

print count

答案 2 :(得分:1)

这是一个非常有效的有趣解决方案。它从不同的角度看问题。

q=int(input())
x=input()

y = x[0: q]

alphabet = {'a': 0, 'b': 0, 'c': 0, 'd': 0, 'e': 0, 'f': 0, 'g': 0, 'h': 0, 'i': 0, 'j': 0,
        'k': 0, 'l': 0, 'm': 0, 'n': 0, 'o': 0, 'p': 0, 'q': 0, 'r': 0, 's': 0, 't': 0,
        'u': 0, 'v': 0, 'w': 0, 'x': 0, 'y': 0, 'z': 0, ' ': 0}

letters = set(list(y))
for letter in letters:
    alphabet[letter] += y.count(letter)

repeats = [i for i in list(alphabet.values()) if i > 1]
singles = len(y)

count = singles
for repeat in repeats:
    count += ((repeat*(repeat - 1))/2)

这里发生了什么?看一个人为的例子,其中y ='abbda efba hia jkla mbnop'并考虑字符'a'。如何计算?

1)每次出现在字符串中时都会计算。这是5次,这是在'alphabet'字典中捕获的。有一个通过字符串中的唯一字符来获取计数。这小于或等于27个字符。我已经包含了空格字符。这也必须计算在内!

2)原始算法也以其他方式计算字符'a'。当它出现在子字符串的两端时计数。在这种情况下,对于出现的第一个'a',我们得到子字符串:

   abba 
   abba efba 
   abba efba hia 
   abba efba hia jkla

对于出现的第二个“a”,还有三个这样的子字符串:

   a efba 
   a efba hia 
   a efba hia jkla

依此类推。因此,我们每次在字符串中计算“a”5次,但也计算4 + 3 + 2 + 1个子字符串,它们位于两端。这只是字母'a'的r(r-1)/ 2个计数。当存在结果的分析表达式时,无需循环。这是算法效率的基础。

答案 3 :(得分:0)

如果我明白你的意思,这就是代码

length = int(input())
s = input()
count = 0
# i: the head index of substring
# j: the tail index of substring, and len(substring) <=length
for i in range(len(s)):
    for j in range(min(length, len(s) - i)):
        if s[i] == s[i + j]:
            count += 1

print(count)

答案 4 :(得分:0)

好吧,你可以避免切片,这会产生不必要的副本:

q = int(input())
x = input()
count = 0
for i in range(q):
    for j in range(q):
        k = j+i+1
        if k<=q:
            if x[i]==x[k] or i==k:
                count+=1

print(count)

更好的是,你可以完全摆脱内循环

q = int(input())
x = input()
count = q
for i in range(q-1):
    if x[i]==x[-i]:
        count+=1

print(count)

我还没有测试过,我正在使用手机......

答案 5 :(得分:0)

算法优化需要您确定松动并将其切除。如果你在没有else块的循环中看到循环变量的条件,那么Flabs会很清楚地突出显示。我们肯定在浪费迭代,应该将其删除

显然,您需要重新运行第二个循环而不是重新计算K,以便您可以删除中间变量j

作为k = j+i+1 0 <=j < q, 我们可以将范围重写为i + 1 <= k < q + i + 1

但我们也知道k&lt; = q所以上述条件可以写成i + 1 <= k < q + 1

所以我们的新功能看起来像

def bar():
    q=int(raw_input())
    x=raw_input()
    count=0
    for i in range(q):
        for k in range(i + 1, q + 1):
            u=x[i:k]
            if u[0]==u[-1] or len(u)==1:
                count+=1
    return count

第二个条件u[0]==u[-1] or len(u)==1很有意思。您正在创建切片并检查前缀和后缀以及长度

肯定是len(u) == k - i == 1,因此您无需重新评估切片并调用函数调用,而是可以写为k == i + 1

def bar():
    q=int(raw_input())
    x=raw_input()
    count=0
    for i in range(q):
        for k in range(i + 1, q + 1):
            if x[i]==x[k - 1] or k  == i + 1:
                count+=1
    return count