您的位置:首页 > 其它

leetcode(139). Word Break

2017-08-11 16:56 423 查看

problem

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. You may

assume the dictionary does not contain duplicate words.

For example, given s = “leetcode”, dict = [“leet”, “code”].

Return true because “leetcode” can be segmented as “leet code”.

solution

一开始我用的是类似于分治算法,先用wordDict中的word在字符串前面去匹配,如果匹配成功则将剩下的继续递归,但是这里面要考虑所有的情况,也就是对一个字符串找出所有前面匹配的情况,然后对这些可能的情况汇总,有一个成功即可。

def OR(ans):
if len(ans) == 0:
return False
elif len(ans) == 1:
return ans[0]
else:
return ans[0] or OR(ans[1:])
class Solution(object):
def wordBreak(self, s, wordDict):
"""
:type s: str
:type wordDict: List[str]
:rtype: bool
"""
if s == "":
return True
ans = []

for word in wordDict:
if s[:len(word)] == word:
ans.append(self.wordBreak(s[len(word):], wordDict))

return OR(ans)


改进

上面的解法类似于爬楼梯问题中的递归解法,即反过来思考,但是对这样的问题反过来思考会出现重复的子问题,如果能将子问题记录下来就会提升很多效率,所以我们正向思考,使用动态规划解法,f(i)定义为前i个字符能否分成合法的word,这样的解法时间复杂度为O(n)。

这个问题不能长word优先或短word优先,反例:

s=’leetcode’, wordDict = [‘lee’, ‘code’, ‘leet’]

s=’leetcode’, wordDict = [‘leetc’, ‘code’, ‘leet’]

#超过了90%
class Solution(object):
def wordBreak(self, s, wordDict):

n = len(s)
ans = [False]*(n+1)
ans[-1] = True
wordDict = set(wordDict)
for i in range(n):
for j in range(i+1):
if s[j:i+1] in wordDict and ans[j-1]:
ans[i] = True
break

print(ans)
return ans[n-1]


改进2

我们在内层循环时可以不遍历整个nums[:i],只遍历wordDict中的最长的长度。

超过了97%的提交。

class Solution(object):
def wordBreak(self, s, wordDict):
n = len(s)
#python2中max没有default
max_len = max([len(string) for string in wordDict] or [0])

can_break = [False for _ in xrange(n + 1)]
can_break[0] = True
for i in xrange(1, n + 1):
for l in xrange(1, min(i, max_len) + 1):
if can_break[i-l] and s[i-l:i] in wordDict:
can_break[i] = True
break

return can_break[-1]


变形

一块长度为n的木棍能否由长度为[i1, i2, … , ik]的短木棍拼成,短木棍数量不限。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode