确定代码的运行时间

Determine running time of the code

本文关键字:运行时间 代码      更新时间:2023-10-16

我今天写了以下dp代码,它工作得很好,因为它得到了一些提交点(这就是问题所在)。然而,我无法确定我的代码的运行时间。我觉得这是O(n^2 * log D),但我无法证明。

class Solution {
public:
    unordered_map<string, bool> m;
    bool wordBreak(string s, unordered_set<string>& wordDict) {
        int n = s.length();
        string t = "";
        for(int i=0;i<n;i++){
            t += s.at(i);
            //cout << t << endl;
            if(wordDict.find(t) != wordDict.end()){
                m[t] = true;
                string x = "";
                for(int j=i+1;j<n;j++){
                    x += s.at(j);
                }
                if(x == ""){
                    return true;
                }
                if(m.find(x) != m.end()){
                    if(m[x] == true){
                        return true;
                    }else{
                        continue;
                    }
                }else{
                    if(wordBreak(x, wordDict)){
                        m[x] = true;
                        return true;
                    }else{
                        //cout << x << endl;
                        m[x] = false;
                        continue;
                    }
                }
            }else{
                //m[t] = false;
            }
        }
        return false;
    }
};

它似乎具有O(n*n)复杂性。你使用记忆和你的算法的每一步产生至少一个新的值在m。在任何字符串中都有n*n/2子字符串,因此在最坏的情况下,您将找到具有n*n/2段的整个字符串的解决方案。

PS:考虑unordered_map与O(1)兼容

编辑:

在您的情况下,认为unordered_map适用于O(n)可能更合适。m.find将需要为它的参数计算哈希值,这是字符串。如果您存储索引而不是字符串本身,可能会工作得更快。

首先我将重写如下(未经测试):

class Solution {
public:
    unordered_map<string, bool> m;
    bool wordBreak(string s, unordered_set<string>& wordDict) 
    {
        while (!s.empty())
        {
        int n = s.size() ;
        for(int i=0;i<n;i++){
            //cout << t << endl;
            if(wordDict.find(s.substr(0, i)) != wordDict.end()){
                m[t] = true;
                s = s.substr(i) ;
                break ;
        }
        return !m.empty();
    }
};

基本思想是,一旦你找到一个匹配,然后你可以从字符串中删除匹配的部分。那么我就说它是n * logD。毕竟,您只在for循环上执行了一次。假设你在m <N,那么你得到一个新的循环(N>

我是这样解决的。

bool wordBreak(string s, unordered_set<string>& wordDict) {
    if (s.empty()) return true;
    vector<bool> dp(s.size(), false);
    for (int i = 0; i < dp.size(); ++i)
    {
        for (int j = i; j >= 0; --j)
        {
            if (wordDict.find(s.substr(j, i - j + 1)) != wordDict.end() &&
                (j == 0 || dp[j - 1]))
            {
                dp[i] = true;
                break;
            }
        }
    }
    return dp.back();
}