【LeetCode每日一题】2020.6.25 139. 单词拆分

139. 单词拆分

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。

示例:

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

输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
输出: false

分析:

​ (1)匹配单词可以想到使用哈希表来存储 单词/布尔值 键值对来表示该字符串是否是wordDict中的单词。

​ (2)思考如何将s进行分隔,以便使用哈希表查询真值。可以使用动态规划来解决这个问题。dp[i] = true 表示s的前i个字符可以被wordDict中的单词匹配(注意:可以是一个单词,也可以是多个单词)。转移方程可以帮我们解决匹配多个单词的问题:\(dp[i] = dp[j]\ \&\&\ wordDictSet[s[i:j]]\)

代码(Golang):

func wordBreak(s string, wordDict []string) bool {
	wordDictSet := make(map[string]bool)
	for _, word := range wordDict {
		wordDictSet[word] = true
	}
	dp := make([]bool, len(s) + 1)
	dp[0] = true
	for i := 1; i < len(s) + 1; i++ {
		for j := 0; j < i; j++ {
			if dp[j] && wordDictSet[s[j:i]] {
				dp[i] = true
				break
			}
		}
	}
	return dp[len(s)]
}

小结:

​ 这道题中使用了动态规划,就可以将一个看起来不好入手的问题分解成几个简单的问题:

  1. 确定字符串的一部分是否匹配成功。

  2. 将这部分字符串的真值 状态传递下去。

  3. 包含这部分字符串的大字符串的状态由小字符串 及 另一部分小字符串的状态决定。

  4. 大的字符串的状态又被转移到更大的字符串。

    做完之后思考这道题的解题步骤,再次感叹动态规划思想的精妙。


猜你喜欢

转载自www.cnblogs.com/enmac/p/13192262.html