1. 拼写单词
给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。
假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。
注意:每次拼写时,chars 中的每个字母都只能用一次。
返回词汇表 words 中你掌握的所有单词的 长度之和。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-words-that-can-be-formed-by-characters/
def countCharacters(self, words, chars):
c_count = collections.Counter(chars)
result = 0
for word in words:
wc_count = collections.Counter(word)
if all(wc_count[c] <= c_count.get(c, 0) for c in wc_count):
result += len(word)
return result
2.单词拆分
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-break
方法一:应用DFS+记忆(超时)
def wordBreak(self, s, wordDict):
def dfs(s, word_dict, sets):
if s in sets:
return True
if not s:
return True
for i in range(1, len(s)+1):
word = s[:i]
if word not in word_dict:
continue
if dfs(s[i:], word_dict, sets):
sets.add(s)
return True
return False
return dfs(s, set(wordDict), set())
方法二:优化,应用Python 缓存机制与 functools.lru_cache
https://blog.csdn.net/qq_19446965/article/details/104070046
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
import functools
@functools.lru_cache(None)
def dfs(s, word_dict):
if len(s) == 0:
return True
for i in range(1, len(s)+1):
word = s[:i]
if word not in word_dict:
continue
if dfs(s[i:], word_dict):
return True
return False
return dfs(s, tuple(wordDict))
3.单词拆分 II
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-break-ii
方法一:DFS+缓存
def wordBreak(self, s, wordDict):
def dfs(s, word_dict, sets):
if s in sets:
return sets[s]
if len(s) == 0:
return []
partitions = []
if s in word_dict:
partitions.append(s)
for i in range(1, len(s)):
word = s[:i]
if word not in word_dict:
continue
sub_partitions = dfs(s[i:], word_dict, sets)
partitions.extend(map(lambda sub_partition: word + " " + sub_partition, sub_partitions))
sets[s] = partitions
return partitions
return dfs(s, set(wordDict), {})
方法二:DFS+内部cache缓存
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
import functools
@functools.lru_cache(None)
def dfs(s):
if len(s) == 0:
return []
partitions = []
if s in wordDict:
partitions.append(s)
for i in range(1, len(s)):
word = s[:i]
if word not in wordDict:
continue
sub_partitions = dfs(s[i:])
partitions.extend(map(lambda sub_partition: word + " " + sub_partition, sub_partitions))
return partitions
return dfs(s)
4.单词接龙
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-ladder
方法:BFS+缓存
def ladderLength(self, beginWord, endWord, wordList):
def get_next_words(word, dict):
words = []
for i in range(len(word)):
for c in 'abcdefghijklmnopqrstuvwxyz':
next_word = word[:i] + c + word[i + 1:]
if next_word != word and next_word in dict:
words.append(next_word)
return words
if endWord not in wordList:
return 0
dict = set(wordList)
queue = [(beginWord, [beginWord])]
depth = 0
distance = set()
while queue:
depth += 1
new_queue = []
for cur, path in queue:
if cur == endWord:
return depth
set_path = set(path)
for next in get_next_words(cur, dict):
if next in distance:
continue
distance.add(next)
if next not in set_path:
new_queue.append((next, path + [next]))
queue = new_queue
return 0
5.单词接龙
给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则:
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-ladder-ii
方法:BFS+缓存
def findLadders(self, beginWord, endWord, wordList):
def get_next_words(word, dict):
words = []
for i in range(len(word)):
for c in 'abcdefghijklmnopqrstuvwxyz':
next_word = word[:i] + c + word[i + 1:]
if next_word != word and next_word in dict:
words.append(next_word)
return words
if endWord not in wordList:
return []
dict = set(wordList)
queue = [(beginWord, [beginWord])]
res = []
depth = 0
distance = {}
min_len = float('inf')
while queue:
depth += 1
new_queue = []
for cur, path in queue:
if cur == endWord:
res.append(path)
continue
set_path = set(path) # 优化,减少遍历时间
for next in get_next_words(cur, dict):
if distance.get(next) and distance.get(next) < depth:
continue
distance[next] = depth
if next not in set_path:
new_queue.append((next, path + [next]))
if res:
break
queue = new_queue
return res