「这是我参与2022首次更文挑战的第40天,活动详情查看:2022首次更文挑战」。
LeetCode 139.单词拆分
题目:给定一个字符串和一个字符串列表,请判断是否可以利用字符串列表中出现的单词拼接出字符串。注意:不要求字符串列表中单词全部使用,但字符串列表中单词可以重复使用。
例如:
输入:s = "leetcode", wordDict = ["leet", "code"]
输出:true。
解释:因为"leetcode"可以由"leet"和"code"拼接得到。
而输入s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]则返回false。
解题思路
本题可转换为完全背包问题,转换后就是一个背包中存有固定数量的物品,现有列表中的物品,要求将列表中的物品转入背包,并且列表中物品不限量,问此列表是否可以装出和背包中物品相同的组合。
此时可以用动态规划来解决本题,设置状态转移数组dp,其中数组中第i个元素dp[i]表示以i-1结尾的字符是否可以由列表中单词组成。则循环字符串,在字符串内部继续循环,此时循环是获取以0开始以外层循环i为终止的字符,截取内层循环的字符,查看列表中是否包含且字符的前一个字符所对应的dp状态为true(重要:这一步可以保证恢复的字符串无重叠部分),如果满足条件则设置此时的状态,代码跳过本次循环开始下一次循环。直到循环到最后一个字符,如果最后一个字符的状态仍为true,则返回true。可得代码如下:
public boolean wordBreak(String s, List<String> wordDict) {
boolean[] dp = new boolean[s.length() + 1];
dp[0] = true; //dp[i] 以i-1结尾的字符串是否可以由wordDict组成
for(int i=1;i<=s.length();i++){
for(int j=0;j<i;j++){
if(dp[j]&&wordDict.contains(s.substring(j, i))){
dp[i] = true;
break;
}
}
}
return dp[s.length()];
}
此代码时间复杂度为,空间复杂度为。