解决“减少弦乐”的挑战

时间:2012-06-28 12:31:43

标签: algorithm dynamic-programming

我已经看过各种讨论和代码尝试解决来自interviewstreet.com的"String reduction"问题,但他们都没有通过动态编程来解决这个问题。

Dynamic Programming部分列出,问题描述如下:

  

给定由a,b和c组成的字符串,我们可以执行以下操作:取任意两个相邻的不同字符并将其替换为第三个字符。例如,如果'a'和'c'相邻,则可以用'b'代替。

     

重复应用此操作 可以产生的最小字符串是什么?

可以使用详尽的强力搜索来解决问题,有效地创建一个包含所有可能替换的树:

// this is more or less pseudo code from my head
int GetMinLength(string s)
{
    // solve edge cases
    if (s.Length == 1) return 1;
    if (s.Length == 2) return ReduceIfPossible(s);

    // recursive brute force
    int min = s.Length;
    for (int i = 0; i<s.Length-1; i++)
    {
        if (s[i] != s[i+1])
        {
            var next = GetMinLength(
                  s.Substring(0, i) + 
                  Reduce(s[i], s[i + 1]) +
                  s.Substring(i + 2)
                  );

            if (next < min) min = next;
        }
    }
}

对于较大的NN <= 100),这显然会失败,所以我试图将其分解为较小的子问题,记住它们并合并结果。

问题在于我无法确定应用动态编程所需的"optimal substructure"状态(换句话说是“合并”子问题的结果)。最小化字符串的一部分并不能保证最终的字符串确实是最小的解决方案。

在这种情况下,子问题“状态”是什么,可以合并为最终解决方案?

3 个答案:

答案 0 :(得分:1)

使这一点变得棘手的是你需要将其视为连续2个动态编程问题。

  1. 建立一个表格,通过起始位置,您可以将所有可能的结束位置(可以缩小为该字符)结束。
  2. 字符串的最后i个字符可以缩小到的最小长度。 (您在步骤1中构建的表可用于递归地将此问题减少到已解决的子问题。)
  3. 第二个提供了你的答案。如果你已经解决了第一个问题,那就简单明了了。

答案 1 :(得分:0)

您首先要创建一个描述解决方案理论的结构。它包括所考虑的字符数,以及到目前为止编码的字符串,以及理论的最坏情况和最佳情况。

一开始只有一种理论 - 没有人物处理过。最佳情况是长度为1的字符串(例如,规则始终适用,字符串可以缩减为一个字符,最坏的情况是N,其中不适用规则)例如。

encoded string = "";
encoded index = 0;
worst case = N; 
best case = 1;

现在开始将索引递增1,并在编码的字符串中添加一个字符。如果没有适用的规则,那么你就不要理会这个理论。如果规则确实适用,您可以做出决定 - 要么应用规则,要么不应用规则。因此,当您添加一个字符时,您可以复制适用于最后一个字符的每个规则的理论,并保留一个版本,不应用任何规则。并为每种理论更新最佳案例和最坏情况。

起初,理论数量会迅速增加。但最终你遇到的情况是某些理论的最坏情况比其他理论的最佳情况要好。

因此,无论何时推进指数,你都会删除理论,其中最好的情况比最坏情况下的理论更糟糕。随着指数接近N,大多数理论都会退出。

答案 2 :(得分:0)

剧透警报代码:

true

<强>复杂度:

这是O(n)时间复杂度操作,随着输入大小的增加,要完成的工作量与输入的大小成线性关系。闪电很快,我们可以处理兆字节大小的字符串,并且仍然可以在几分之一秒内处理它们。

此处的算法充分分析了此算法的工作原理:

stumped on a Java interview, need some hints