单词拆分(Leetcode-139)-记忆化搜索&DFS

题目

知识点

  • 记忆化搜索

思路

  • 虽然是一个个单词,但本质可以看作是路径寻找问题,字符串s每个字符相当于一个路径节点,问是否能从以第一个字母为节点开始,找到最后一个字符结束的路径,如下为例子:

    输入: s = “applepenapple”, wordDict = [“apple”, “pen”]
    输出: true
    "apple"相当于0->4有一条路,8->12有一条路(单词可重复使用)
    "pen"相当于5->7有一条路

  • 那么,在上述的例子中,我们可以找到一条路径满足问题,即0->4 再到 5->7 再到 8->12

  • 问题在于如何获得每个单词能够产生的“路径”。注意,例如上述中的例子apple可以出现两次(因为相同单词可以使用多次)。因此,在开始的时候先构建路径图。我们对于一个单词,需要从头到尾搜索一遍(Line 29-46),检索在 s 中的位置。因为 find() 只能找到第一个子串,所以用 while 设置循环,每次寻找子串开始位置向后一位继续查找。我使用了 map<int, vector<int>> m 记录了所有可能走的路径,在后面DFS找路径的时候,m[当前位置] 即可获得这个位置出发,所有能够到达的位置。

  • 但是,但是… 单一这样的方法只能过30+数据,不能过全部的数据,因此我们还需要进行优化。

记忆化搜索

  • 其实就是动态规划那味…
  • 使用 int vis[1000] 去记录当前这个位置是否被访问过(-1 - 未访问,0 - 访问过但走不通,1-访问了走得通)。即:如果被访问了,当前位置出发是否能够到达。
  • 当然在这道题里找到了就逐层返回true了(可以用两位表示,这里我就直接用 int 类型了)…所以在这题里,vis 就是用于告诉我们该位置已经走过了,是走不通的,别走了别走了!浪费时间(Line 9)
  • Line 14-21 就是向下搜索的过程,如果当前位置可以继续往下走 m.count(depth) ,那我们就一个个向下搜索,如果全部向下走都不行,那我们从该位置出发就是行不通的,因此把这个位置 vis 标记为0 (Line 23)

代码

  • PS:我的方法代码虽然长一点,但是速度好像比一般的更快哈哈~
    单词拆分(Leetcode-139)-记忆化搜索&DFS
class Solution {
public:
    map<int, vector<int>> m;  // index - 位置
    int ed;
    int vis[1000];

    bool dfs(int depth) {
        int &ans = vis[depth];
        if (ans != -1) return ans;  // 这个depth后续访问已经做过,是走不通的

        if (depth == ed) return true;
        if (depth > ed) return false;

        if (m.count(depth)) {
            for (int i:m[depth]) {
                if (dfs(i + 1)) {
                    ans = 1;  // 这个depth可以走
                    return true;
                }
            }
        }
        ans = 0;
        return false;
    }

    bool wordBreak(string s, vector<string> &wordDict) {
        ed = s.size();
        memset(vis, -1, sizeof(int[1000]));
        for (const string &i:wordDict) {
            int b = 0, index;
            bool end = false;
            while (!end) {
                if (b > s.size()) break;
                index = s.find(i, b);
                if (index != -1) {
                    if (!m.count(index)) {
                        m[index] = vector<int>(1, index + i.size() - 1);
                    } else {
                        m[index].emplace_back(index + i.size() - 1);
                    }
                    b += 1;
                } else {
                    end = true;
                }
            }
        }
        return dfs(0);
    }
};
上一篇:深度估计 DenseDepth 笔记


下一篇:如何查看全局安装的包