JS算法-单词拆分

151 阅读2分钟

题目

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。

输入: s = "applepenapple", wordDict = ["apple", "pen"]
输出: true
解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。
     注意,你可以重复使用字典中的单词。

题解

第一种

首先,定义一个长度为len的数组dp,用于记录字符串s的前i个字符能否被拆分成若干个在字典中出现过的单词。接下来遍历字符串s的前i个字符,假设当前处理到了第i个字符,则:如果s的前i个字符是一个在字典中出现过的单词,则令dp[i]为true。如果s的前i个字符不是一个在字典中出现过的单词,则需要分别考虑以第j个字符为结尾、第i个字符为开头的子串subCur,其中j的范围从0到i。对于每个子串subCur,只有当subCur是一个在字典中出现过的单词,且dp[j-1]为true,即s的前j-1个字符可以被拆分成若干个在字典中出现过的单词,才能令dp[i]为true。最终返回dp[len-1]的值,即整个字符串s是否可以被拆分成若干个在字典中出现过的单词

var wordBreak = function (s, wordDict) {
    let len = s.length
    let dp = new Array(len).fill(false)

    for (let i = 0; i < len; i++) {
        let cur = s.substring(0, i + 1)
        if (wordDict.indexOf(cur)>-1) {
            dp[i] = true
        } else {
            for (let j = 0; j <= i; j++) {
                let subCur = s.substring(j, i + 1)
                dp[i] = dp[i] || (wordDict.indexOf(subCur)>-1 && dp[j - 1])
            }
        }
    }
    return dp[len - 1]
};

第二种

定义一个长度为 n+1 的数组 dp,其中 dp[i] 表示前 i 个字符是否可以拆分成 wordDict 中的单词。首先要将 wordDict 转化为一个 Set,方便后面的查找操作。初始化 dp[0] 为 true,因为空字符串肯定可以由 wordDict 中的单词组成。接下来是动态转移方程,对于每一个 i,都在从 0 到 i-1 的范围内进行循环。如果 dp[j] 为 true,且 s 的子串从 j 开始、长度为 i-j 的子串也在 wordDict 中出现,则将 dp[i] 设为 true 并跳出内层循环,因为已经找到一种拆分方案了。最后返回 dp[n] 即可,表示整个字符串是否可以被拆分成 wordDict 中的单词

 var wordBreak = function(s, wordDict) {
  const n = s.length;
  const wordDictSet = new Set(wordDict);
  const dp = new Array(n+1).fill(false);
  dp[0] = true;
  for(let i = 1;i<=n;i++){
    for(let j = 0;j<i;j++){
      if(dp[j] && wordDictSet.has(s.substr(j,i-j))){
        dp[i] = true;
        break;
      }
    }
  }
  return dp[n];
};

坚持努力,无惧未来!