我不确定如何立即降低空间复杂度,但是,您可以使用动态编程来避免检查重复项,从而降低时间复杂度。通过一些额外的努力,通常也可以降低动态规划问题的空间复杂度。
存在一个最优子结构,因为路径只是独立但重叠的前缀的总和(a+a = aa,aa+a = aaa)。考虑到这一点,我们可以通过以下方式解决 3x3 的问题。
纸笔法:
已确定第一选择的解决方案 - a、b、c。
我们需要确定第二选择、第三选择等的解决方案。
通过连接 row + col 确定两个前缀 - 两列可用的选项。
a b c
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
b ba bb bc
c ca cb cc
获取我们刚刚创建的前缀并将它们应用于我们最初的 1x1 解决方案 - row + col
a b c
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
咩咩咩咩
ca caa 出租车 cac
ab aba abc
bb bba bbb 英国广播公司
cb cba cbb cbc
ac aca acb ac
bc bca bcb bcc
cc cca ccb ccc
n*n 解决方案就是这种方法重复 n-1 次。
我也是用 C# 写出来的
class Program
{
static void Main(string[] args)
{
int sizeOf = 3; //size of problem - ex 3x3
var vals = "abcdefghijklmnop".ToCharArray(); //up to 16 (abc in ex)
//Create initial problem
String[] x = new String[sizeOf];
String[] y = new String[sizeOf];
for (int i = 0; i < x.Length; i++)
{
x[i] = vals[i].ToString();
y[i] = vals[i].ToString();
}
//hold our solutions
String[][] result = null;
String[] temp = x;
for (int i = 1; i < y.Length; i++)
{
result = getCombos(temp, y);
temp = (from k in result
from l in k
select l).ToArray();
}
//Flatten out solution
var finalResult = (from k in result
from l in k
select l).ToList();
printArray(finalResult);
Console.WriteLine("Total Count: {0}", finalResult.Count());
}
static void printArray(List<String> a)
{
foreach (var x in a)
{
Console.Write("{0} ", x);
}
Console.WriteLine();
}
static String[][] getCombos(String[] x, String[] y)
{
//Initialize array to hold solution
String[][] prefixes = new String[x.Length][];
for (int j = 0; j < x.Length; j++)
{
prefixes[j] = new String[y.Length];
}
//concat to form solution
for (var i = 0; i < x.Length; i++)
{
for (var j = 0; j < y.Length; j++)
{
prefixes[i][j] = x[i] + y[j];
}
}
return prefixes;
}
}
在空间复杂度变得太多之前,我将它运行到了 9x9。这是一个非常有趣的问题。