1. 程式人生 > >leetcode 139 單詞拆分

leetcode 139 單詞拆分

給定一個非空字串 s 和一個包含非空單詞列表的字典 wordDict,判定 s 是否可以被空格拆分為一個或多個在字典中出現的單詞。

說明:

  • 拆分時可以重複使用字典中的單詞。
  • 你可以假設字典中沒有重複的單詞。

示例 1:

輸入: s = "leetcode", wordDict = ["leet", "code"]
輸出: true
解釋: 返回 true 因為 "leetcode" 可以被拆分成 "leet code"。

動態規劃

       用一個一維的dp陣列,其中dp[i]表示範圍[0, i)內的子串是否可以拆分,注意這裡dp陣列的長度比s串的長度大1,是因為我們要handle空串的情況,我們初始化dp[0]為true,然後開始遍歷。注意這裡我們需要兩個for迴圈來遍歷,因為此時已經沒有遞迴函數了,所以我們必須要遍歷所有的子串,我們用j把[0, i)範圍內的子串分為了兩部分,[0, j) 和 [j, i),其中範圍 [0, j) 就是dp[j],範圍 [j, i) 就是s.substring(j, i),其中dp[j]是之前的狀態,我們已經算出來了,可以直接取,只需要在字典中查詢s.substring(j, i)是否存在了,如果二者均為true,將dp[i]賦為true,並且break掉,此時就不需要再用j去分[0, i)範圍了,因為[0, i)範圍已經可以拆分了。最終我們返回dp陣列的最後一個值,就是整個陣列是否可以拆分的布林值了。

public boolean wordBreak(String s, List<String> wordDict) {
    int n = s.length();
    boolean[] dp = new boolean[n + 1];
    dp[0] = true;
    for(int i = 1; i <= n; i++){
        for(int j = 0; j < i; j++){
            if(dp[j] && wordDict.contains(s.substring(j, i))){
                dp[i] = true;
                break;
            }
        }
    }
    return dp[n];
}