我从 interviewstreet.com 看到了各种讨论和尝试解决“字符串缩减”问题的代码,但没有一个是通过动态编程来解决的。
列在动态规划部分下,问题描述如下:
给定一个由 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;
}
}
}
N
对于较大的( ),这显然会失败N <= 100
,因此我试图将其分解为较小的子问题,记忆它们并合并结果。
问题是我无法确定具有“最佳子结构”的状态,需要应用动态编程(或者换句话说,“合并”子问题的结果)。最小化字符串的一部分并不能保证最终的字符串确实是最小的解决方案。
在这种情况下,可以合并到最终解决方案的子问题“状态”是什么?