LeetCode 820.題目-中等
1.題目
原題鏈接
給定一個單詞列表,我們將這個列表編碼成一個索引字符串 S 與一個索引列表 A。
例如,如果這個列表是 [“time”, “me”, “bell”],我們就可以將其表示爲 S = “time#bell#” 和 indexes = [0, 2, 5]。
對於每一個索引,我們可以通過從字符串 S 中索引的位置開始讀取字符串,直到 “#” 結束,來恢復我們之前的單詞列表。
那麼成功對給定單詞列表進行編碼的最小字符串長度是多少呢?
示例
輸入: words = [“time”, “me”, “bell”]
輸出: 10
說明: S = “time#bell#” , indexes = [0, 2, 5] 。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/two-sum
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
2.解題
問題的本質是找出所有無法成爲別的單詞的後綴的單詞。
方法一:所有單詞放入集合,依次刪除每個單詞的後綴
相關知識:
set.discard()
思路:
- 因爲在hash set中刪除操作效率高。而且放入集合可以去重。所以先講words數組放入set中
- 對每個單詞。遍歷它的所有後綴。並從set中刪除
- 注意使用set.discard()方法而不是remove()方法。後者若刪除元素不存在會報錯,而前者不會。
- 複雜度分析:
時間複雜度 , 其中是 words[i] 的長度。每個單詞有個後綴,對於每個後綴,查詢其是否在集合中時需要進行的哈希值計算。
空間複雜度 , 存儲單詞的空間開銷
class Solution:
def minimumLengthEncoding(self, words: List[str]) -> int:
good = set(words)
for word in words:
for k in range(1,len(word)):
good.discard(word[k:])
return sum(len(word)+1 for word in good)
方法二:字典樹
相關知識:
能自動賦初始值的字典-collections.defaultdict()方法
python中的lambda關鍵字
字典樹Trie
python中的reduce()方法-序列迭代方法
python中的特殊方法__getitem__()方法
python中的enumerate()函數-返回枚舉對象
使用__getitem__魔法函數實現多層嵌套字典:博主自己實現了多層嵌套字典的__getitem__方法,並指出collections.defaultdict類中已經實現了類似的方法(這也就是我們下面用到的)
思路:
- 利用數組的in方法和List的index方法
- 遍歷數組的數nums[i],通過in方法**target-num[i]**判斷是否在數組內,如果在,則使用index方法獲得下標。(注意要判斷是否是使用了重複的元素)
class Solution:
def minimumLengthEncoding(self, words: List[str]) -> int:
words = list(set(words)) # 去掉重複。必須要去掉重複!
Trie = lambda: collections.defaultdict(Trie) # lambda構造函數,嵌套字典
trie = Trie()
# getitem方法能使對應字典出現key,但value是空的{}
# Trie是一個嵌套字典.
# 對任一word[i]:S來說,reduce可以看成是一個循環,嵌套過程,
# 完成reduce()操作能得到Trie[S[0]][S[1]][S[2]]...[S[len(S)-1]]的值,記爲L[i]
# 對所有words進行這一操作, 就完成了嵌套字典的生成過程
# 若word[i]不是別的單詞的後綴, 則L[i]必是空{},即len(L[i])==0
# 若word[i]是別的單詞的後綴, 則L{i}必有值
L = [reduce(dict.__getitem__, word[::-1], trie) for word in words]
return sum(len(word)+1 for i, word in enumerate(words) if len(L[i]) == 0)