题意:
解题思路:
思路:时间复杂度:O(n2)1. 初始化 dp=[False,~,False],长度为 n+1。n 为字符串长度,dp[i]表示s的前i位是否可以用wordDict中的单词表示。2. 初始化 dp[0]=True,空字符可以被表示。3. 遍历字符串的所有子串,遍历开始索引 i,遍历区间 [1, n): * 遍历结束索引j,遍历区间 [0~i): 若 dp[j]=True 且 s[i,⋯,j) 在 wordlist中:dp[i] = True。 解释:dp[j]=True说明 s 的前 j 位可以用 wordDict表示,则 s[i,⋯,j) 出现在 wordDict 中,说明 s 的前 i 位可以表示。4. 返回 dp[n]首先,s[0:4]=='leet' 是wordDict内的单词,所以dp[4]=True。继续以0为起点,4以后的索引为终点的单词都不在字典内,选择忽略。即'leetc','leetco','leetcod','leetcode'都不在字典内,忽略不管。第二步,因为之前设置了DP[4]=True,所以迭代至4为起点查看后面的单词是否在字典内。发现s[4:8]=='code' 在字典内,所以设置DP[8]为True,至此循环结束。
PHP代码实现:
class Solution { /** * @param String $s * @param String[] $wordDict * @return Boolean */ function wordBreak($s, $wordDict) { $dp = [0 => true] + array_fill(1, strlen($s), false); for ($i = 0; $i < strlen($s); $i++) { for ($j = 1; $j <= strlen($s); $j++) { if ($dp[$i] && in_array(substr($s, $i, $j - $i), $wordDict)) { $dp[$j] = true; } } } return end($dp); } function wordBreak2($s, $wordDict) { $n = strlen($s); $dp = array_fill(0, $n + 1, false); $dp[0] = true; for ($i = 1; $i <= $n; $i++) { for ($j = 0; $j < $i; $j++) { $word = substr($s, $j, $i - $j); if ($dp[$j] && in_array($word, $wordDict)){ $dp[$i] = true; break; } } } return $dp[$n]; } function wordBreak1($s, $wordDict) { $memo = []; return $this->helper($s, $wordDict, 0, $memo); } function helper($s, $wordDict, $start, &$memo) { if ($start == strlen($s)) return true; if (isset($memo[$start])) return $memo[$start]; for ($end = $start + 1; $end <= strlen($s); ++$end) { if (in_array(substr($s, $start, $end - $start), $wordDict) && $this->helper($s, $wordDict, $end, $memo)) { $memo[$start] = true; return true; } } $memo[$start] = false; return false; }}
GO代码实现:
func wordBreak(s string, wordDict []string) bool { wordDictSet := make(map[string]bool) for _, v := range wordDict { wordDictSet[v] = true } dp := make([]bool, len(s) + 1) dp[0] = true for i := 1; i <= len(s); i++ { for j := 0; j<i; j++ { if dp[j] && wordDictSet[s[j:i]] { dp[i] = true break } } } return dp[len(s)]}