forked from azl397985856/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
lucifer
committed
Feb 4, 2020
1 parent
2057b5e
commit 1d86136
Showing
6 changed files
with
154 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
## 题目地址(472. 连接词) | ||
|
||
https://leetcode-cn.com/problems/concatenated-words/ | ||
|
||
## 题目描述 | ||
|
||
``` | ||
给定一个不含重复单词的列表,编写一个程序,返回给定单词列表中所有的连接词。 | ||
连接词的定义为:一个字符串完全是由至少两个给定数组中的单词组成的。 | ||
示例: | ||
输入: ["cat","cats","catsdogcats","dog","dogcatsdog","hippopotamuses","rat","ratcatdogcat"] | ||
输出: ["catsdogcats","dogcatsdog","ratcatdogcat"] | ||
解释: "catsdogcats"由"cats", "dog" 和 "cats"组成; | ||
"dogcatsdog"由"dog", "cats"和"dog"组成; | ||
"ratcatdogcat"由"rat", "cat", "dog"和"cat"组成。 | ||
说明: | ||
给定数组的元素总数不超过 10000。 | ||
给定数组中元素的长度总和不超过 600000。 | ||
所有输入字符串只包含小写字母。 | ||
不需要考虑答案输出的顺序。 | ||
``` | ||
|
||
## 思路 | ||
|
||
本题我的思路是直接使用前缀树来解决。**标准的前缀树模板**我在之前的题解中提到了,感兴趣的可以到下方的相关题目中查看。 | ||
|
||
这道题这里我们不需要 search,我们的做法是: | ||
|
||
- 先进行一次遍历,将 words 全部插入(insert)到前缀树中。 | ||
- 然后再进行一次遍历,查找每一个单词有几个单词表中的单词组成 | ||
- 如果大于 2,则将其加入到 res 中 | ||
- 最后返回 res 即可 | ||
|
||
我们构造的前缀树大概是这样的: | ||
|
||
![472.concatenated-words.png](http://ww1.sinaimg.cn/large/e9f490c8ly1gbkcox4r06j21eb15fgq8.jpg) | ||
|
||
问题的关键在于第二步中的**查找每一个单词有几个单词表中的单词组成**。 其实如果你了解前缀树的话应该不难写出来。 比如查找 catsdogcats: | ||
|
||
- 我们先从 c 到 a 到 t,发现 t 是单词结尾,我们数量 + 1 | ||
- 然后将剩下的部分“sdogcats”重新执行上述过程。 | ||
- s 发现找不到,我们返回 0 | ||
- 因此最终结果是 1 | ||
|
||
很明显这个逻辑是错误的,正确的划分应该是: | ||
|
||
- 我们先从 c 到 a 到 t,再到 s,此时数量 + 1 | ||
- 然后将剩下的“dogcats”重复上述过程 | ||
- dog 找到了,数量 + 1 | ||
- 最后将 cats 加入。也找到了,数量再加 1 | ||
|
||
由于我们并不知道 cat 这里断开,结果更大?还是 cats 这里断开结果更大?因此我们的做法是将其全部递归求出,然后取出最大值即可。如果我们直接这样递归的话,可能会超时,卡在最后一个测试用例上。一个简单的方式是记忆化递归,从而避免重复计算,经测试这种方法能够通过。 | ||
|
||
## 代码 | ||
|
||
代码支持:Python3 | ||
|
||
Python3 Code: | ||
|
||
```python | ||
class Trie: | ||
|
||
def __init__(self): | ||
self.Trie = {} | ||
self.visited = {} | ||
|
||
def insert(self, word): | ||
curr = self.Trie | ||
for w in word: | ||
if w not in curr: | ||
curr[w] = {} | ||
curr = curr[w] | ||
curr['#'] = 1 | ||
|
||
def cntWords(self, word): | ||
if not word: | ||
return 0 | ||
if word in self.visited: | ||
return self.visited[word] | ||
curr = self.Trie | ||
res = float('-inf') | ||
|
||
for i, w in enumerate(word): | ||
if w not in curr: | ||
return res | ||
curr = curr[w] | ||
if '#' in curr: | ||
res = max(res, 1 + self.cntWords(word[i + 1:])) | ||
self.visited[word] = res | ||
return res | ||
|
||
|
||
class Solution: | ||
def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]: | ||
self.trie = Trie() | ||
res = [] | ||
|
||
for word in words: | ||
self.trie.insert(word) | ||
for word in words: | ||
if self.trie.cntWords(word) >= 2: | ||
res.append(word) | ||
return res | ||
``` | ||
|
||
## 关键点分析 | ||
|
||
- 前缀树 | ||
|
||
## 相关题目 | ||
|
||
- [208.implement-trie-prefix-tree](https://github.com/azl397985856/leetcode/blob/b8e8fa5f0554926efa9039495b25ed7fc158372a/problems/208.implement-trie-prefix-tree.md) | ||
- [211.add-and-search-word-data-structure-design](https://github.com/azl397985856/leetcode/blob/b0b69f8f11dace3a9040b54532105d42e88e6599/problems/211.add-and-search-word-data-structure-design.md) | ||
- [212.word-search-ii](https://github.com/azl397985856/leetcode/blob/b0b69f8f11dace3a9040b54532105d42e88e6599/problems/212.word-search-ii.md) | ||
- [0472.concatenated-words](./problems/472.concatenated-words.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
## 前缀树问题 | ||
|
||
截止目前(2020-02-04) [前缀树(字典树)](https://leetcode-cn.com/tag/trie/) 在 LeetCode 一共有 17 道题目。其中 2 道简单,8 个中等,7 个困难。 | ||
|
||
这里总结了四道题,弄懂这几道, 那么前缀树对你应该不是大问题, 希望这个专题可以帮到正在学习前缀树 的你。 | ||
|
||
前缀树的 api 主要有以下几个: | ||
|
||
- `insert(word)`: 插入一个单词 | ||
- `search(word)`:查找一个单词是否存在 | ||
- `startWith(word)`: 查找是否存在以 word 为前缀的单词 | ||
|
||
其中 startWith 是前缀树最核心的用法,其名称前缀树就从这里而来。大家可以先拿 208 题开始,熟悉一下前缀树,然后再尝试别的题目。 | ||
|
||
一个前缀树大概是这个样子: | ||
|
||
![](https://github.com/azl397985856/leetcode/raw/b8e8fa5f0554926efa9039495b25ed7fc158372a/assets/problems/208.implement-trie-prefix-tree-1.png) | ||
|
||
如图每一个节点存储一个字符,然后外加一个控制信息表示是否是单词结尾,实际使用过程可能会有细微差别,不过变化不大。 | ||
|
||
以下是本专题的四道题目的题解,内容会持续更新,感谢你的关注~ | ||
|
||
- [208.implement-trie-prefix-tree](https://github.com/azl397985856/leetcode/blob/b8e8fa5f0554926efa9039495b25ed7fc158372a/problems/208.implement-trie-prefix-tree.md) | ||
- [211.add-and-search-word-data-structure-design](https://github.com/azl397985856/leetcode/blob/b0b69f8f11dace3a9040b54532105d42e88e6599/problems/211.add-and-search-word-data-structure-design.md) | ||
- [212.word-search-ii](https://github.com/azl397985856/leetcode/blob/b0b69f8f11dace3a9040b54532105d42e88e6599/problems/212.word-search-ii.md) | ||
- [472.concatenated-words](https://github.com/azl397985856/leetcode/blob/master/problems/472.concatenated-words.md) |