首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >这个回文分割算法的时间复杂度是多少?

这个回文分割算法的时间复杂度是多少?
EN

Stack Overflow用户
提问于 2014-07-06 00:14:48
回答 2查看 6.3K关注 0票数 8

回文分区

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

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

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

代码语言:javascript
运行
复制
#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();
        }
    }
}
};
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-06 01:43:31

最坏的运行时间是O(n * 2^n)。当然,这是指数级的,但不像O(n^n)那么糟糕。

下面是我如何获得O(n * 2^n):顶级函数有一个O(n^2)循环来初始化备忘录,然后调用整个字符串的助手。因此,如果我们用(s.length()-start)等于n的调用助手的代价编写H(n),那么算法的总成本将是

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

H(n)的基本情况是,当s.length() - start = 1时,它只是复制列表的成本:

H(1) = O(n)

对于递归情况,如果每次if条件memo[start][end]true,则对size (n- 1 )、(n- 2 )、(n-3)、.、2、1进行(n-1)递归调用。除了对helper的递归调用外,还必须调用相同大小的substr函数,总共要花费O(n^2)。因此,对n>1而言,H(n)的总体成本是

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

(我会把它写成求和,但不支持LaTeX。)

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

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

这解决了

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

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

Note:您可以通过在一个O(n^3)循环中预先计算所有子字符串来稍微改进这一点。您也可以对memo数组执行同样的操作。然而,这并没有改变渐近大O界。

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

票数 5
EN

Stack Overflow用户

发布于 2015-07-06 03:52:02

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

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

票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24591616

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档