leetcode每日一题(2020-06-25):139. 单词拆分

题目描述:
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。

今日学习:
1.动规动规动动规
2.回溯

题解:天使,永远的神:https://leetcode-cn.com/problems/word-break/solution/shou-hui-tu-jie-san-chong-fang-fa-dfs-bfs-dong-tai/

//没有回溯会导致丢失很多情况,此为不正确题解
var wordBreak = function(s, wordDict) {
    let temp = i = 0
    while(i < s.length) {
        i = temp
        for(let j = i + 1; j < s.length; j++) {
            let word = s.slice(i, j)
            if(wordDict.indexOf(word) != -1) {
                temp = j
                break
            }
        }
        if(i == temp) {
            return false
        }
    }
    return true
}
//单纯回溯还会超时,所以要加个标识
var wordBreak = function (s, wordDict) {
  const wordSet = new Set(wordDict);
  const memo = new Array(s.length);        // 存 子问题的状态(指针)和子问题的解
  const check = (s, wordSet, start, memo) => {
    if (start > s.length - 1) return true; // start已经越界,结束递归
    if (memo[start] !== undefined) return memo[start];  // memo中有,直接返回它
    for (let end = start + 1; end <= s.length; end++) { // 固定start 考察所有的end
      const word = s.slice(start, end); // 前缀单词
      if (wordSet.has(word) && check(s, wordSet, end, memo)) {//前缀单词是单词表里的
        memo[start] = true; // 并且递归剩余子串的结果也是true,则将当前结果存入memo
        return true;        // 当前子问题的结果是true
      }
    }
    memo[start] = false;    // 当前子问题的结果是false
    return false; // start固定,end遍历了所有字符都没有返回true,则返回false
  };
  return check(s, wordSet, 0, memo); // 递归的入口
};
//BFS回溯
var wordBreak = function (s, wordDict) {
  const wordSet = new Set(wordDict);
  const visited = new Array(s.length);
  const queue = [0];                      // 先考察start位置0
  while (queue.length) {
    const start = queue.shift();          // 考察出列节点
    if (visited[start] == true) continue; // 跳过访问过的
    visited[start] = true;                // 访问了 记录一下
    for (let end = start + 1; end <= s.length; end++) { // 固定start 考察所有end
      const word = s.slice(start, end);   // 开头的单词
      if (wordSet.has(word)) {            // 单词表有这个单词
        if (end > s.length - 1) return true; // 并且end已经越界,说明考察完了s串
        queue.push(end);                  // 将下一层的end推入队列
      }
    }
  }
  return false;
};
//动规
var wordBreak = function (s, wordDict) {
  const wordSet = new Set(wordDict);
  const len = s.length;
  const dp = new Array(len + 1).fill(false);
  dp[0] = true;
  for (let i = 1; i <= len; i++) {
    for (let j = i; j >= 0; j--) {
      const word = s.slice(j, i);
      if (wordSet.has(word) && dp[j] == true) {
        dp[i] = true;
        break;
      }
    }
  }
  return dp[s.length];
};

猜你喜欢

转载自www.cnblogs.com/autumn-starrysky/p/13191389.html