天天看點

Leetcode:139.單詞拆分&&140.單詞拆分II

139.單詞拆分

給定一個非空字元串 s 和一個包含非空單詞清單的字典 wordDict,判定 s 是否可以被空格拆分為一個或多個在字典中出現的單詞。

說明:

  • 拆分時可以重複使用字典中的單詞。
  • 你可以假設字典中沒有重複的單詞。

示例 1:

輸入: s = "leetcode", wordDict = ["leet", "code"]
輸出: true
解釋: 傳回 true 因為 "leetcode" 可以被拆分成 "leet code"。
      

示例 2:

輸入: s = "applepenapple", wordDict = ["apple", "pen"]
輸出: true
解釋: 傳回 true 因為          "                applepenapple         "                 可以被拆分成          "                apple pen apple         "                。
     注意你可以重複使用字典中的單詞。
      

示例 3:

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

解題思路:

深度優先搜尋(DFS),動态規劃(DP),字元串哈希。

1. 字元串wordDict進入哈希表。這裡可以用unorderded_map來實作比較友善。期間還可以統計單詞的最小長度min和最大長度max。

2. 從pos=0開始處搜尋,查找長度為[min,max]的子串,max還要根據s的規模确定是否溢出。每得到一個單詞在map中出現,就遞歸。

3. 為了防止已經搜尋的路徑重複搜尋,應該建立bool dp[10001],儲存已經通路過的路徑。

Leetcode:139.單詞拆分&&140.單詞拆分II

C++代碼

class Solution {

public:

    bool wordBreak(string s, vector<string>& wordDict) {

        int size = wordDict.size(), i;

        if (size == 0) return false;

        ss = s;

        for (i = 1; i <= size; i++) {

            mp[wordDict[i - 1]] = true;

            if (int(wordDict[i - 1].size()) > max) max = int(wordDict[i - 1].size());

            if (int(wordDict[i - 1].size()) < min) min = int(wordDict[i - 1].size());

        }

        length = s.size();

        if (length == 0) return false;

        return DFS(0);

    }

    bool DFS(int pos) {

        if (pos == length) return true;

        int left = min, right = max;

        if (right + pos - 1 >= length) right = length - pos;

        string str;

        bool sgn;

        for (int i = left; i <= right; i++) {

            str = ss.substr(pos, i);

            if (mp[str] == true) {

                if (dp[pos + i] != 0) {

                    sgn = (dp[pos + i] == -1 ? false : true);

                }

                else {

                    sgn = DFS(pos + i);

                    dp[pos + i] = (sgn == true ? 1 : -1);

                }

                if (sgn == true) return true;

            }

            else { mp.erase(str); }

        }

        return false;

    }

private:

    int dp[10001];

    unordered_map<string, bool> mp;

    int max = 0, min = INT32_MAX;

    int length;

    string ss;

};

140.單詞拆分II

給定一個非空字元串 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"]
輸出:
[]      

解題思路:

和139一緻,隻不過要儲存每一種搜尋的結果。

Leetcode:139.單詞拆分&amp;&amp;140.單詞拆分II

C++代碼

class Solution {

public:

    vector<string> wordBreak(string s, vector<string>& wordDict) {

        int size = wordDict.size(), i;

        if (size == 0) return{};

        ss = s;

        for (i = 1; i <= size; i++) {

            mp[wordDict[i - 1]] = true;

            if (int(wordDict[i - 1].size()) > max) max = int(wordDict[i - 1].size());

            if (int(wordDict[i - 1].size()) < min) min = int(wordDict[i - 1].size());

        }

        length = s.size();

        if (length == 0) return{};

        vector<string> res = DFS(0);

        return res;

    }

    vector<string> DFS(int pos) {

        visit[pos] = true;

        if (pos >= length) {

            dp[pos].push_back("");

            return{ "" };

        }

        int left = min, right = max;

        if (right + pos - 1 >= length) right = length - pos;

        string str, sgn, str1;

        vector<string> vs;

        for (int i = left; i <= right; i++) {

            str = ss.substr(pos, i);

            if (mp[str] == true) {

                int size = dp[pos + i].size();

                if (visit[pos+i] == true) {

                    vs = dp[pos + i];

                }

                else {

                    vs = DFS(pos + i);

                }

                for (int j = 1; j <= int(vs.size()); j++) {

                    if (vs[j - 1] == "") { dp[pos].push_back(str); }

                    else dp[pos].push_back(str +" "+ vs[j - 1]);

                }

            }

            else mp.erase(str);

        }

        return dp[pos];

    }

private:

    vector<string> dp[10001];

    bool visit[10001];

    unordered_map<string, bool> mp;

    int max = 0, min = INT32_MAX;

    int length;

    string ss;

};