題目及測試
package pid140;
/*單詞拆分 II
給定一個非空字符串 s 和一個包含非空單詞列表的字典 wordDict,在字符串中增加空格來構建一個句子,使得句子中所有的單詞都在詞典中。返回所有這些可能的句子。
說明:
分隔時可以重複使用字典中的單詞。
你可以假設字典中沒有重複的單詞。
示例 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"]
輸出:
[]
*/
import java.util.ArrayList;
import java.util.List;
public class main {
public static void main(String[] args) {
String [] testTable = {"catsanddog","applepenapple","catsandog"};
List<List<String>> testTable2=new ArrayList<List<String>>();
List<String> list=new ArrayList<>();
list.add("cat");
list.add("cats");
list.add("and");
list.add("sand");
list.add("dog");
testTable2.add(list);
list=new ArrayList<>();
list.add("apple");
list.add("pen");
testTable2.add(list);
list=new ArrayList<>();
list.add("cats");
list.add("dog");
list.add("sand");
list.add("and");
list.add("cat");
testTable2.add(list);
for(int i=0;i<testTable.length;i++){
test(testTable[i], testTable2.get(i));
}
}
private static void test(String ito,List<String> ito2) {
Solution solution = new Solution();
List<String> rtn;
long begin = System.currentTimeMillis();
System.out.print(ito);
System.out.println();
for(String str:ito2){
System.out.print(str+" ");
}
System.out.println();
//開始時打印數組
rtn= solution.wordBreak(ito,ito2);//執行程序
long end = System.currentTimeMillis();
System.out.println("rtn=" );
for(String str:rtn){
System.out.println(str+" ");
}
System.out.println();
System.out.println("耗時:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(不成功,應該是對的,超時)
建立一個List<List<String>> lists,lists[i] 代表[0,i]的字符串,拆分後的字符串數組。
之前的[0,j],新的單詞(j,i],每次將之前的lists[j] 加上空格,加上符合要求的s.subString(j+1,i+1)
package pid140;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Solution {
public List<String> wordBreak(String s, List<String> wordDict) {
int length=s.length();
if(length==0){
return new ArrayList<String>();
}
Set<String> set=new HashSet<>(wordDict);
// lists[i] 代表[0,i]的字符串,拆分後的字符串數組
List<List<String>> lists=new ArrayList<>();
for(int i=0;i<length;i++){
lists.add(new ArrayList<>());
}
for(int i=0;i<length;i++){
List<String> list=lists.get(i);
for(int j=-1;j<i;j++){
// 之前的[0,j],新的單詞(j,i]
// j=-1,[0,-1],(-1,i]
// j=0,[0,0],(0,i]
// j=1,[0,1],(1,i]
// j=i-1,[0,i-1],(i-1,i]
if(j==-1){
if(set.contains(s.substring(0, i+1))){
list.add(s.substring(0, i+1));
}
}else{
if(lists.get(j).size()>0&&set.contains(s.substring(j+1, i+1))){
for(String str:lists.get(j)){
list.add(str+" "+s.substring(j+1, i+1));
}
}
}
}
}
return lists.get(length-1);
}
}
解法2(別人的)
這個方法背後的想法是對於給定的問題(s),它可以被拆分成子問題 s1s1s1 和 s2s2s2 。如果這些子問題分別都能滿足條件,那麼整個文字 s 也可以滿足。比方說, "catsanddog" 可以被拆分成子字符串 "catsand" 和 "dog" 。子問題 "catsand" 進一步可以被拆分成 "cats" 和 "and" ,它們分別都是字典的一部分,所以 "catsand" 也是滿足條件的。遞歸回來,因爲 "catsand" 和 "dog" 分別都滿足要求,所以原字符串 "catsanddog" 也符合要求。
現在,我們來考慮 dp 數組如何求出。我們使用長度爲 n+1n+1n+1 的數組 dp ,其中 n 是給定字符串的長度。 dp[k] 被用來存儲用 s[0:k−1]可被拆分成合法單詞的句子。我們同事用兩個指針 i 和 j ,其中 i 表示子字符串 s′ 的長度(s′ 是 s 的一個前綴), j 表示 s′ 的拆分位置,即拆分成 s′(0,j) 和 s′(j+1,i) 。
爲了求出 dp 數組,我們將 dp[0] 初始化爲空串。我們以 i 爲結尾表示的子字符串的所有前綴,通過指針 j 將 s 拆分成 s1′ 和 s2′ 。爲了求出dp[i] ,我們檢查所有 dp[j] 包含的所有非空字符串,也就是所有能形成 s1′ 的句子。如果存在,我們進一步檢查 s2′ 是否在字典裏,如果兩個條件都滿足,我們將子字符串 s2′ 添加到所有 s1′ 的句子的後面(這些句子已經保存在了 dp[j] 裏面),並將這些新形成的句子保存進(dp[i])。最終, dp[n] (n 是給定字符串 s 的長度)裏面保存了所有可以得到完整字符串 s 的所有句子。
public class Solution {
public List<String> wordBreak(String s, Set<String> wordDict) {
LinkedList<String>[] dp = new LinkedList[s.length() + 1];
LinkedList<String> initial = new LinkedList<>();
initial.add("");
dp[0] = initial;
for (int i = 1; i <= s.length(); i++) {
LinkedList<String> list = new LinkedList<>();
for (int j = 0; j < i; j++) {
if (dp[j].size() > 0 && wordDict.contains(s.substring(j, i))) {
for (String l : dp[j]) {
list.add(l + (l.equals("") ? "" : " ") + s.substring(j, i));
}
}
}
dp[i] = list;
}
return dp[s.length()];
}
}