这个算法的时间复杂度是多少?(动态规划)



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

返回所有这些可能的句子。

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

解决方案是["猫和狗","猫沙狗"]。


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

我个人认为,

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

困惑者:

  • 无法弄清楚动态规划的时间复杂度。
  • 看来上面的空间复杂度是不正确的。


代码[爪哇]
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);
        }
    }
}

使用 DP:

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

内存: O(N(

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

动态规划 - 分词

这是动态问题。

你可以维护两件事。

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(,你可以使用矢量pre[i]来获得你想要的所有切割解决方案。

最新更新