Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么';回文分割算法的时间复杂度是多少?_C++_Algorithm_Big O_Dynamic Programming_Palindrome - Fatal编程技术网

C++ 什么';回文分割算法的时间复杂度是多少?

C++ 什么';回文分割算法的时间复杂度是多少?,c++,algorithm,big-o,dynamic-programming,palindrome,C++,Algorithm,Big O,Dynamic Programming,Palindrome,回文分区 给定一个字符串s,分区s使得 分区是回文。返回所有可能的回文 s的分区。 我个人认为,时间复杂度是O(n^n),n是给定字符串的长度 谢谢Dan Roche,时间紧迫复杂度=O(n*(2^n)),请查看下面的详细信息 #包括 使用名称空间std; 类解决方案{ 公众: 向量分区(字符串s){ 向量表; 向量子列表; //输入验证。 如果(s.length()=j)memo[i][j]=true; else memo[i][j]=假; } } int start=0; 助手(s、开始、列

回文分区

给定一个字符串s,分区s使得 分区是回文。
返回所有可能的回文 s的分区。

我个人认为,时间复杂度是O(n^n),n是给定字符串的长度

谢谢Dan Roche,时间紧迫复杂度=O(n*(2^n)),请查看下面的详细信息

#包括
使用名称空间std;
类解决方案{
公众:
向量分区(字符串s){
向量表;
向量子列表;
//输入验证。
如果(s.length()=j)memo[i][j]=true;
else memo[i][j]=假;
}
}
int start=0;
助手(s、开始、列表、子列表、备忘录);
退货清单;
}
void helper(字符串s,int start,
向量和列表,向量和子列表,
向量和备忘录){
//基本情况。
如果(开始>s.长度()-1){
向量1_rest(子列表);
列表。推回(剩余一个);
返回;
}

对于(int len=1;start+len来说,最坏情况下的运行时间是O(n*2^n)。这当然是你所怀疑的指数,但没有O(n^n)那么糟糕

下面是我如何得到O(n*2^n):您的顶级函数有一个O(n^2)循环来初始化memo,然后在整个字符串上调用helper。因此,如果我们用
(s.length()-start)
等于n来写H(n)作为调用helper的代价,那么您的算法的总代价将是

成本=H(n)+O(n^2)

H(n)的基本情况是
s.length()-start
等于1,然后这只是复制列表的成本:

H(1)=O(n)

对于递归情况,如果
if
条件
memo[start][end]
每次都是
true
,那么大小(n-1)、(n-2)、(n-3)将有(n-1)个递归调用,…,2,1。除了这些对
helper
的递归调用外,您还必须在相同的大小上调用
substr
函数,这总共花费O(n^2)。因此,对于n>1,H(n)的总成本为

H(n)=H(n-1)+H(n-2)+…+H(1)+O(n^2)

(我会把它写成一个总结,但SO没有LaTeX的支持。)

现在,您可以为H(n-1)编写相同的表达式,然后替换回以简化:

H(n)=2h(n-1)+O(n)

这就解决了

H(n)=O(n*2^n)

因为它大于O(n^2),所以整个成本也是O(n*2^n)


注意:您可以通过在单个O(n^3)循环中预先计算所有子字符串来稍微改进这一点。您也可以对
memo
数组执行相同的操作。但是,这不会改变渐近大O界

事实上,O(n*2^n)是最优的,因为在最坏的情况下,字符串是相同字符的n次重复,如“aaaaaa”,在这种情况下,有2^n个可能的分区,每个分区的大小为n,总输出大小为Ω(n*2^n)。

应该是O(n*2^n)。您基本上是在尝试所有可能的分区。对于长度为n的字符串,您将有2^(n-1)种方式对其进行分区。这是因为,分区相当于在b/t两个字符中放置“|”。有n-1个这样的插槽来放置“|”。每个插槽只有两种选择—放置“|”或不放置“|”。因此2^(n-1)放置“|”s的方法


然后对于每个唯一的分区,您必须遍历整个字符串(在最坏的情况下,当您有重复字符时),以确保每个分区都是回文。因此n*2^(n-1)=O(n*2^n)。

分区中的算法看起来像O(n^2)对我来说,但我不确定如何理解你的
助手
,因为它是递归的,而且我还没有在头脑中运行它。谢谢你,戴。因为在一个递归中有一个循环,这对我来说也很难在头脑中运行它。如果你想,我有一个O(n^2)解决方案。我可以发布解决方案。你是如何得出
H(n)=2*H(n-1)+O(n)
?是(a)
H(n-1)=H(n-2)+H(n-3)+…+H(1)+O(n-1)^2
;(b)
O(n^2)=O(n)+O(n-1)^2
,因此
H(n)=H(n-1)+[H(n-2)+O(n-1)^2]+O(n)=2*H(n-1)(n-O(n)
?这是正确的吗?我不确定(b)是合法的还是不正确的。@ma“有点松动”在我关于(b)的推理中,关键是被减去的两个大O实际上是同一个函数。更迂腐的是,我们应该定义一个函数g(n)=调用大小(n-1)、(n-2),…,1的
substr
。然后我们有
H(n)=H(n-1)+…+H(1)+g(n)
,现在可以简化为
H(n) =2*H(n-1)+g(n)-g(n-1)
。最后,您说差异
g(n)-g(n-1)
是在大小
(n-1)
上调用
substr
的时间,这是
O(n)
#include <vector>
using namespace std;

class Solution {
public:
vector<vector<string>> partition(string s) {
    vector<vector<string>> list;
    vector<string> subList;

    // Input validation.
    if (s.length() <= 1) {
        subList.push_back(s);
        list.push_back(subList);
        return list;
    }

    int len = s.length();
    vector<vector<bool>> memo(len, vector<bool>(len));
    for (int i = 0; i < len; i ++) {
        for (int j = 0; j < len; j ++) {
            if (i >= j) memo[i][j] = true;
            else memo[i][j] = false;
        }
    }

    int start = 0;
    helper(s, start, list, subList, memo);

    return list;
}

void helper(string s, int start, 
            vector<vector<string>> &list, vector<string> &subList,
            vector<vector<bool>> &memo) {

    // Base case.
    if (start > s.length() - 1) {
        vector<string> one_rest(subList);
        list.push_back(one_rest);
        return;
    }

    for (int len = 1; start + len <= s.length(); len ++) {
        int end = start + len - 1;

        memo[start][end] = (len == 1) ||
                           (memo[start + 1][end - 1] && s[start] == s[end]);

        if (memo[start][end] == true) {
            // Have a try.
            subList.push_back(s.substr(start, len));

            // Do recursion.
            helper(s, end + 1, list, subList, memo);

            // Roll back.
            subList.pop_back();
        }
    }
}
};