Leetcode139. Word Break

Leetcode139. Word Break

Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.
Note:
The same word in the dictionary may be reused multiple times in the segmentation.
You may assume the dictionary does not contain duplicate words.

Example 1:

Input: s = "leetcode", wordDict = ["leet", "code"]
Output: true
Explanation: Return true because "leetcode" can be segmented as "leet code".

Example 2:

Input: s = "applepenapple", wordDict = ["apple", "pen"]
Output: true
Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
             Note that you are allowed to reuse a dictionary word.

Example 3:

Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
Output: false

解法一 动态规划

思路
  • 遍历字符串的所有子字符串[i,j),字符串长度为n
  • 遍历开始的索引为 i,遍历区间 [0,n),遍历结束的索引为j,遍历区间[i+1,n+1)
  • dp[i]=Trues[i,⋯,j)在 wordlist 中:dp[j]=True
第 1 步:定义状态

dp[i] 表示 s 的前 i 位是否可以用 wordDict 中的单词表示。注意数组长度要定义为n+1

第 2 步:思考状态转移方程

动态规划方法的递推公式可以简略的表示为:

dp[i] = ( dp[i-1] && contains(subStr(i-1,i))  )
        || (  dp[i-2] && contains(subStr(i-2,i))  )
        || (  dp[i-3] && contains(subStr(i-3,i))  ) 
        || ...
第 3 步:思考初始值

初始化dp[i]falsedp[0]=true

第 4 步:思考输出

输出dp[i]

|T| | | | | | | | |
 0 1 2 3 4 5 6 7 8

i = 1
j = o sub = l

i = 2
j = 0 sub = le
j = 1 sub = e

i = 3
j = 0 sub = lee
j = 1 sub = ee
j = 2 sub = e

i = 4
j = 0 sub = leet && T[0] and then break, no need to check for rest
|T| | | |T| | | | |
 0 1 2 3 4 5 6 7 8

i = 5
j = 0 sub = leetc
j = 1 sub = eetc
j = 2 sub = etc
j = 3 sub = tc
j = 4 sub = c

i = 6
j = 0 sub = leetco
j = 1 sub = eetco
j = 2 sub = etco
j = 3 sub = tco
j = 4 sub = co
j = 5 sub = o

i = 7
j = 0 sub = leetcod
j = 1 sub = eetcod
j = 2 sub = etcod
j = 3 sub = tcod
j = 4 sub = cod
j = 5 sub = od
j = 6 sub = d

i = 8
j = 0 sub = leetcode
j = 1 sub = eetcode
j = 2 sub = etcode
j = 3 sub = tcode
j = 4 sub = code && T[4] and then break

|T| | | |T| | | |T|
 0 1 2 3 4 5 6 7 8
public boolean wordBreak(String s, List<String> wordList) {
    boolean[] T = new boolean[s.length() + 1];
    Set<String> set = new HashSet<>();
    for (String word : wordList) {
        set.add(word);
    }
    T[0] = true;
    for (int i = 1; i <= s.length(); i++) {
        for (int j = 0; j < i; j++) {
            if(T[j] && set.contains(s.substring(j, i))) {
                T[i] = true;
                break;
            }
        }
    }
    return T[s.length()];
}

Python

class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:       
        n=len(s)
        dp=[False]*(n+1)
        dp[0]=True
        for i in range(n):
            for j in range(i+1,n+1):
                if(dp[i] and (s[i:j] in wordDict)):
                    dp[j]=True
        return dp[-1]

优化:先将wordDict存到字典{ }中,因为s[j:i] in wordDict的时间复杂度是O(n)。

Java implementation using DP in two ways

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值