[LeetCode 140. 单词拆分 II] | 刷题打卡

253 阅读2分钟

一、题目描述

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。

说明:

  • 分隔时可以重复使用字典中的单词。
  • 你可以假设字典中没有重复的单词。

示例 1:

输入:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
输出:
[
  "cats and dog",
  "cat sand dog"
]

示例 2:

输入:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
输出:
[
  "pine apple pen apple",
  "pineapple pen apple",
  "pine applepen apple"
]
解释: 注意你可以重复使用字典中的单词。

示例 3:

输入:
s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
输出:
[]

来源:力扣(LeetCode) 链接:单词拆分 II

二、算法思路

简单介绍一下, 这题做了两次(一次是刷题过程中遇到的, 一次是每日一题遇到的). 两次写的都是回溯, 然后超时了. 这题LeetCode有个很狗的数据, 所以要多做一步剪枝优化, 在这里记录一下

预处理一个数组f, f[i]表示从i这个位置开始到最后的字符串是否可以被划分为字典中的单词.

状态转移, j表示保留到的位置. 那么f[i] = f[j + 1] && 【s[i ~ j]在字典中存在】 最后就是dfs暴力搜索答案, 中途剪枝. 防止TLE.

三、AC代码

/**
 * @param {string} s
 * @param {string[]} wordDict
 * @return {string[]}
 */
var wordBreak = function(s, wordDict) {
    const ans = [], n = s.length;
    const hash = {};
    for(let word of wordDict) hash[word] = true;
    const f = Array.from({length: n + 1}, () => false);
    f[n] = true;
    for(let i = n - 1; ~i; -- i)
        for(let j = i; j < n; ++ j)
            if(f[j + 1] && hash[s.substr(i, j - i + 1)])
                f[i] = true;
    dfs(0, "");
    return ans;
    function dfs(u, path) {
        if(u == n) ans.push(path.substr(0, path.length - 1));
        else {
            for(let i = u; i < n; ++ i)
                if(hash[s.substr(u, i - u + 1)] && f[i + 1])
                    dfs(i + 1, path + s.substr(u, i - u + 1) + " ");
        }
    }
};

本文正在参与「掘金 3 月闯关活动」,点击查看活动详情