难以理解的 Leetcode 140 解决方案

Posted

技术标签:

【中文标题】难以理解的 Leetcode 140 解决方案【英文标题】:Hard to understand Leetcode 140 solution 【发布时间】:2020-07-30 20:34:27 【问题描述】:

对于来自 LeetCode https://leetcode.com/problems/word-break-ii/ 的这个问题,我已经看到了下一个解决方案:

class Solution 
private:
    unordered_map<string, vector<string>> dp;
public:
    vector<string> wordBreak(string s, vector<string>& wordDict) 
        if(dp.find(s) != dp.end())
            return dp[s];
        vector<string> result;
        for(string w : wordDict)
        
            if(s.substr(0, w.length()) == w)
            
                if(w.length() == s.length())
                    result.push_back(w);
                else
                
                    vector<string> temp = wordBreak(s.substr(w.length()), wordDict);
                    for(string t : temp)
                        result.push_back(w + " " + t);
                
            
        
        dp[s] = result;
        return result;
    
;

有人可以帮我理解它是如何工作的吗?我发现这种递归很难理解。

【问题讨论】:

一般来说比赛代码不是为了被理解而写的。它旨在快速编写并在特定硬件上快速运行一次。很多时候它不值得学习。 理解代码的最好方法是在调试器中启动它并逐行浏览代码。 你试过用调试器看看它是如何工作的吗? 【参考方案1】:

这应该更容易理解:

#include <bits/stdc++.h>
using namespace std;

string s = "pineapplepenapple";
int n;
unordered_set<string> dict("apple", "pen", "applepen", "pine", "pineapple");

void solve(vector<string> &v, int index = 0)
    if(index >= n)
        for(int i = 0; i < v.size(); i++)
            cout<<v[i]<<" ";
        
        cout<<endl;
        return;
    
    for(int i = index; i < n; i++)
        string sub = s.substr(index, i - index + 1);
        if(dict.find(sub) != dict.end())
            v.push_back(sub);
            solve(v, i + 1);
            v.pop_back();
        
    


int main()
    vector<string> v;
    n = s.size();
    solve(v);
    return 0;

输出

pine apple pen apple 
pine applepen apple 
pineapple pen apple 

为了更好地解释,我将solve 分成几部分。

void solve(vector<string> &v, int index = 0)

v 存储每个有效单词以便最后打印。 index 是我们目前正在查看的字符。

    if(index >= n)
        for(int i = 0; i < v.size(); i++)
            cout<<v[i]<<" ";
        
        cout<<endl;
        return;
    

这是递归的基本情况,当索引大于或等于字符串本身的大小时,意味着它到达了它的末尾。

    for(int i = index; i < n; i++)
        string sub = s.substr(index, i - index + 1);
        if(dict.find(sub) != dict.end())
            v.push_back(sub);
            solve(v, i + 1);
            v.pop_back();
        
    

for 循环查看原始字符串的每个子字符串(从索引开始),例如:ppipinpine、...,当其中之一子字符串在字典中,将其放入v 并再次调用该方法,从该子字符串结束后的索引开始。

最后,当递归返回时,我们从v 中删除子字符串,因为我们想尝试其他的。

提供的解决方案与此解决方案的区别在于,提供的解决方案使用动态规划来存储每个子字符串有多少可能性,因此如果之前已经计算过solve(a, b),则不需要再次计算。这对您来说应该不难扩展。

【讨论】:

以上是关于难以理解的 Leetcode 140 解决方案的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode刷题模版:131 - 140

LeetCode刷题模版:131 - 140

android布局中出现难以理解的错误,如何发现问题并解决?

电脑缺少msvcp140,dll解决办法

msvcp140.dll丢失的解决方法_msvcp140.dll丢失怎样修复

电脑msvcp140.dll丢失的解决方法?