140. 单词拆分 II
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
说明:
分隔时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-break-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
字典树
import java.util.*;
class Solution {
private Trie trie;
private List<String> ans = new ArrayList<>();
private LinkedList<String> item = new LinkedList<>();
private void addToAns() {
ans.add(String.join(" ", item));
}
private void solve(String s, int index) {
if (index == s.length()) {
addToAns();
return;
}
Trie.Node cur = trie.getRoot();
for (int i = index; i < s.length(); ++i) {
char path = s.charAt(i);
Trie.Node child = cur.children.get(path);
if (child == null) {
return;
}
if (child.end) {
item.offerLast(s.substring(index, i + 1));
solve(s, i + 1);
item.pollLast();
}
cur = child;
}
}
public List<String> wordBreak(String s, List<String> wordDict) {
this.trie = new Trie();
this.trie.insert(wordDict);
solve(s, 0);
return ans;
}
}
class Trie {
private Node root = new Node();
class Node {
Map<Character, Node> children = new HashMap<>();
boolean end;
}
public Node getRoot() {
return root;
}
public void insert(List<String> strs) {
for (String str : strs) {
insert(str);
}
}
private void insert(String str) {
Node cur = root;
for (int i = 0; i < str.length(); ++i) {
char path = str.charAt(i);
Node child = cur.children.get(path);
if (child == null) {
child = new Node();
cur.children.put(path, child);
}
cur = child;
}
cur.end = true;
}
}
记忆化搜索
class Solution {
public List<String> wordBreak(String s, List<String> wordDict) {
Map<Integer, List<List<String>>> map = new HashMap<Integer, List<List<String>>>();
List<List<String>> wordBreaks = backtrack(s, s.length(), new HashSet<String>(wordDict), 0, map);
List<String> breakList = new LinkedList<String>();
for (List<String> wordBreak : wordBreaks) {
breakList.add(String.join(" ", wordBreak));
}
return breakList;
}
public List<List<String>> backtrack(String s, int length, Set<String> wordSet, int index, Map<Integer, List<List<String>>> map) {
if (!map.containsKey(index)) {
List<List<String>> wordBreaks = new LinkedList<List<String>>();
if (index == length) {
wordBreaks.add(new LinkedList<String>());
}
for (int i = index + 1; i <= length; i++) {
String word = s.substring(index, i);
if (wordSet.contains(word)) {
List<List<String>> nextWordBreaks = backtrack(s, length, wordSet, i, map);
for (List<String> nextWordBreak : nextWordBreaks) {
LinkedList<String> wordBreak = new LinkedList<String>(nextWordBreak);
wordBreak.offerFirst(word);
wordBreaks.add(wordBreak);
}
}
}
map.put(index, wordBreaks);
}
return map.get(index);
}
}
心之所向,素履以往 生如逆旅,一苇以航
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理