Closed azl397985856 closed 3 years ago
由于题目和 140. 单词拆分 II 一样, 因此我就以力扣的这道题讲好了。
实际上这道题就是暴力回溯就好了, 代码也比较简单。
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
ans = []
n = len(s)
def backtrack(temp, start):
if start == n: ans.append(temp[1:])
for i in range(start, n):
if s[start:i + 1] in wordDict:
backtrack(temp + " " + s[start:i + 1], i + 1)
backtrack('', 0)
return ans
复杂度分析
上面的代码会超时,测试用例会挂在如下:
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"]
也就是说 s 的长度是 151, 这超时也就能够理解了,但是力扣的题目描述没有给数据范围。 如果是真实的面试, 一定先问清楚数据范围。
接下来,我们考虑优化。
通过观察发现, 对于一个字符串 s,比如 "helloworldhi" 而言,假设 dict 为:
{
hi: true,
h: true,
i: true,
world: true,
hello: true,
}
我们也不难看出, 当我们DFS探到worldhi的时候,其可能的结果就是探测到的单词和上一步的所有可能的笛卡尔积。
因此一种优化思路就是将回溯的结果通过返回值的形式传递给父级函数,父级函数通过笛卡尔积构造 ans即可。而这实际上和上面的解法复杂度是一样的, 但是经过这样的改造,我们就可以使用记忆化技巧减少重复计算了。因此理论上, 我们不存在回溯过程了。 因此时间复杂度就是所有的组合,即一次遍历以及内部的笛卡尔积,也就是 $O(N ^ 2)$。
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
n = len(s)
def backtrack(start):
ans = []
if start == n:
ans.append('')
for i in range(start, n):
if s[start:i + 1] in wordDict:
if start == 0: temp = s[start:i + 1]
else: temp = " " + s[start:i + 1]
ps = backtrack(i + 1)
for p in ps:
ans.append(temp + p)
return ans
return backtrack(0)
复杂度分析
这种记忆化递归的方式和 DP 思想一模一样, 大家可以将其改造为 DP,这个留给大家来完成。
我整理的 1000 多页的电子书已经开发下载了,大家可以去我的公众号《力扣加加》后台回复电子书获取。
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
这是微软 4 面的编程题。
题目描述
将给定的字符串进行分割, 分割的依据是使得分割后的单词全部在字典 dict 中,如果分割后不在 dict 中, 则返回空。
eg:
力扣类似题目
扩展
完整的微软面经,参考 https://dev.to/dhilipkmr/software-engineer-2-ui-interview-at-microsoft-1i0b