连接词
难度:
标签:
题目描述
给你一个 不含重复 单词的字符串数组 words
,请你找出并返回 words
中的所有 连接词 。
连接词 定义为:一个完全由给定数组中的至少两个较短单词(不一定是不同的两个单词)组成的字符串。
示例 1:
输入: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" 组成。
示例 2:
输入:words = ["cat","dog","catdog"] 输出:["catdog"]
提示:
1 <= words.length <= 104
1 <= words[i].length <= 30
words[i]
仅由小写英文字母组成。words
中的所有字符串都是 唯一 的。1 <= sum(words[i].length) <= 105
代码结果
运行时间: 132 ms, 内存: 30.4 MB
// Java Stream Solution
// 思路:与Java解决方案类似,我们使用一个Set来存储所有的单词。我们遍历每一个单词,
// 使用Stream和递归方法来检查它是否可以由其他单词组成。为了防止自我匹配,我们在检查时
// 临时从Set中移除当前单词。
import java.util.*;
import java.util.stream.Collectors;
public class StreamSolution {
private Set<String> wordSet;
public List<String> findAllConcatenatedWordsInADict(String[] words) {
wordSet = Arrays.stream(words).collect(Collectors.toSet());
return Arrays.stream(words)
.filter(this::canForm)
.collect(Collectors.toList());
}
private boolean canForm(String word) {
if (wordSet.contains(word)) return true;
return IntStream.range(1, word.length())
.mapToObj(i -> new String[] {word.substring(0, i), word.substring(i)})
.anyMatch(parts -> wordSet.contains(parts[0]) && canForm(parts[1]));
}
}
解释
方法:
该题解采用DFS的思路来判断一个单词是否为连接词。对于每个单词,枚举其所有可能的分割点,如果分割点左右两部分都在单词集合中,或者左边部分在单词集合中且右边部分可以进一步分割成多个在单词集合中的子串,那么该单词就是一个连接词。为了避免重复计算,使用lru_cache对dfs函数进行记忆化搜索。
时间复杂度:
O(n*l^2)
空间复杂度:
O(n*l)
代码细节讲解
🦆
为什么在该题解中选用DFS而非其他算法?
▷🦆
题解中提到了使用lru_cache进行记忆化搜索,这是基于什么考虑?记忆化搜索对解决该问题有哪些具体的优势?
▷🦆
在DFS函数中,枚举分割点的范围是从`min_word_length`到`len(word) - min_word_length + 1`,这样设定范围的原因是什么?
▷🦆
如何处理和优化在单词数组中存在大量重复单词的情况?
▷相关问题
单词拆分 II
给定一个字符串 s
和一个字符串字典 wordDict
,在字符串 s
中增加空格来构建一个句子,使得句子中所有的单词都在词典中。以任意顺序 返回所有这些可能的句子。
注意:词典中的同一个单词可能在分段中被重复使用多次。
示例 1:
输入:s = "catsanddog
", wordDict =["cat","cats","and","sand","dog"]
输出:["cats and dog","cat sand dog"]
示例 2:
输入:s = "pineapplepenapple", wordDict = ["apple","pen","applepen","pine","pineapple"] 输出:["pine apple pen apple","pineapple pen apple","pine applepen apple"] 解释: 注意你可以重复使用字典中的单词。
示例 3:
输入:s = "catsandog", wordDict = ["cats","dog","sand","and","cat"] 输出:[]
提示:
1 <= s.length <= 20
1 <= wordDict.length <= 1000
1 <= wordDict[i].length <= 10
s
和wordDict[i]
仅有小写英文字母组成wordDict
中所有字符串都 不同