【问题标题】:What's time complexity of this Algorithm for breaking words? (Dynamic Programming)这个断词算法的时间复杂度是多少? (动态编程)
【发布时间】:2014-08-11 01:46:53
【问题描述】:

分词(使用动态编程:自上而下)
给定一个字符串 s 和一个单词字典 dict,在 s 中添加空格来构造一个句子 其中每个单词都是有效的字典单词。

返回所有可能的句子。

例如,给定
s = "catsanddog",
dict = ["cat", "cats", "and", "sand", "dog"]。

一个解决方案是["cats and dog", "cat sand dog"]。


问题:
  • 时间复杂度?
  • 空间复杂度?

我个人认为,

  • 时间复杂度 = O(n!),没有动态规划,n 是给定字符串的长度,
  • 空间复杂度 = O(n)。

困惑者:

  • 无法通过动态规划计算时间复杂度。
  • 上面的空间复杂度好像不正确。


代码[Java]
public class Solution {
    public List<String> wordBreak(String s, Set<String> dict) {
        List<String> list = new ArrayList<String>();

        // Input checking.
        if (s == null || s.length() == 0 || 
            dict == null || dict.size() == 0) return list;

        int len = s.length();

        // memo[i] is recording,
        // whether we cut at index "i", can get one of the result.
        boolean memo[] = new boolean[len];
        for (int i = 0; i < len; i ++) memo[i] = true;

        StringBuilder tmpStrBuilder = new StringBuilder();
        helper(s, 0, tmpStrBuilder, dict, list, memo);

        return list;
    }

    private void helper(String s, int start, StringBuilder tmpStrBuilder,
                        Set<String> dict, List<String> list, boolean[] memo) {

        // Base case.
        if (start >= s.length()) {
            list.add(tmpStrBuilder.toString().trim());
            return;
        }

        int listSizeBeforeRecursion = 0;
        for (int i = start; i < s.length(); i ++) {
            if (memo[i] == false) continue;

            String curr = s.substring(start, i + 1);
            if (!dict.contains(curr)) continue;

            // Have a try.
            tmpStrBuilder.append(curr);
            tmpStrBuilder.append(" ");

            // Do recursion.
            listSizeBeforeRecursion = list.size();
            helper(s, i + 1, tmpStrBuilder, dict, list, memo);

            if (list.size() == listSizeBeforeRecursion) memo[i] = false;

            // Roll back.
            tmpStrBuilder.setLength(tmpStrBuilder.length() - curr.length() - 1);
        }
    }
}

【问题讨论】:

    标签: algorithm recursion big-o dynamic-programming recursive-backtracking


    【解决方案1】:

    使用 DP:

    时间:O(N*M) N - 字符串大小 M - 字典大小

    内存:O(N)

    在这里查看我的答案,带有代码示例:

    Dynamic Programming - Word Break

    【讨论】:

    • 嗨@maxihatop,非常感谢,我真的希望知道如何证明或如何获得时间复杂度 = O(N*M),从迭代版本中可以清楚地看到,但是我希望能得到这个递归的时间复杂度表达式,比如T(n) = aT(n - ?) + O(1),如果能提供证明真是太好了,非常感谢:)跨度>
    【解决方案2】:

    这是动态问题。

    你可以维护两件事。

    1 dp[i] 表示当字符串在第 i 个字符时,有 dp[i] 的方式来切割它。

    2向量pre[i]表示前一个位置可以到达当前第i个位置。(大小必须为DP[i])

    时间是 O(n*m)

    首先,i在[0,n)中:

    然后在[0,i)中找到j:那个子串(j+1,i)是有效的。

    验证可以预先计算。所以时间是O(n*m),你可以使用vectorpre[i]得到你想要的所有切割解。

    【讨论】:

      猜你喜欢
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多