簡體   English   中英

如何提高python dict的性能?

[英]How to improve python dict performance?

我最近使用dictoionaries編碼了python解決方案,該字典獲得了TLE裁決。 該解決方案與工作中的c ++中的多集解決方案完全相似。 因此,我們確定邏輯是正確的,但是實現方法不盡人意。

用於理解以下代碼的問題描述( http://codeforces.com/contest/714/problem/C ):

  • 對於每個數字,我們需要獲取一個0和1的字符串,如果第i個數字的偶數/奇數,則第i個數字為0/1。
  • 我們需要維護具有與上述點所給定的相同映射的數量計數。

有任何提示/指針可以改善以下代碼的性能嗎? 它為大型測試用例( http://codeforces.com/contest/714/submission/20594344 )授予TLE(超過時間限制)。

from collections import defaultdict

def getPattern(s):
    return ''.join(list(s.zfill(19)))

def getSPattern(s):
    news = s.zfill(19)
    patlist = [ '0' if (int(news[i])%2 == 0) else '1'   for i in range(19) ]
    return "".join(patlist)


t = int(raw_input())
pat = defaultdict(str)  # holds strings as keys and int as value

for i in range(0, t):
    oper, num = raw_input().strip().split(' ')

    if oper == '+' :
        pattern = getSPattern(str(num))
        if pattern in pat:
            pat[pattern] += 1
        else:
            pat[pattern] = 1
    elif oper == '-' :
        pattern = getSPattern(str(num))
        pat[pattern] =  max( pat[pattern] - 1, 0)
    elif oper == '?' :
        print pat.get(getPattern(num) , 0 )

我發現您的代碼有很多小問題,但無法說出它們是否會導致嚴重的性能問題:

您已經錯誤地設置並使用了defaultdict()

pat = defaultdict(str)
...
if pattern in pat:
    pat[pattern] += 1
else:
    pat[pattern] = 1

defaultdict()構造函數的參數應該是值的類型,而不是鍵。 正確設置defaultdict后,您只需執行以下操作:

pat = defaultdict(int)
...
pat[pattern] += 1

因為如果模式不存在,該值現在默認為零。

由於規范說:

-ai-從多集中刪除一次出現的非負整數ai。 可以肯定的是,多集中至少有一個ai。

然后這樣:

pat[pattern] =  max( pat[pattern] - 1, 0)

可以簡單地是這樣的:

pat[pattern] -= 1

您正在使用19個字符串,但是由於規范指出數字將小於10 ** 18,因此您可以改用18個字符串。

getSPattern()執行zfill()然后處理字符串,它應該以相反的順序執行,先處理字符串,然后zfill()處理,因為不需要在前導零上運行邏輯。

我們不需要int()的開銷即可將字符轉換為數字:

(int(news[i])%2 == 0)

考慮使用ord()代替,因為數字的ASCII值與數字本身具有相同的奇偶校驗: ord('4') -> 52

而且您不需要循環索引,只需循環字符即可。

以下是通過上述更改對代碼進行的重做,看看它是否仍然有效(!)並獲得任何性能:

from collections import defaultdict

def getPattern(string):
    return string.zfill(18)

def getSPattern(string):
    # pattern_list = (('0', '1')[ord(character) % 2] for character in string)
    pattern_list = ('0' if ord(character) % 2 == 0 else '1' for character in string)
    return ("".join(pattern_list)).zfill(18)

patterns = defaultdict(int)  # holds keys as strings as and values as int

text = int(raw_input())

for _ in range(text):
    operation, number = raw_input().strip().split()

    if operation == '+':
        pattern = getSPattern(number)
        patterns[pattern] += 1
    elif operation == '-':
        pattern = getSPattern(number)
        patterns[pattern] -= 1
    elif operation == '?':
        print patterns.get(getPattern(number), 0)

使用@cdlane已經完成的解釋,我只需要在我認為花費大量時間的地方添加對getSPattern重寫getSPattern 根據我的初步評論,這可在https://eval.in/641639上獲得

def getSPattern(s):
    patlist = ['0' if c in ['0', '2', '4', '6', '8'] else '1' for c in s]
    return "".join(patlist).zfill(19)

使用zfill(18)可能會稍微節省您一些時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM