Java 递归除法数组

Java 递归除法数组,java,algorithm,recursion,time-complexity,Java,Algorithm,Recursion,Time Complexity,我需要得到许多可能的方法来将数组划分为小的子数组。我们可以将阵列纵向和横向分开。我的算法很好,但是时间复杂度太差了。你能看看如何改进它吗 参数 nStart-子数组的第一行 nEnd-子数组的最后一行 mStart,mEnd-用于第二维度(列) check()-函数检查结束条件 return-不同数组分割方法的编号。我们在函数检查返回true时进行除法 public static long divide(int nStart, int nEnd, int mStart, int mEnd) {

我需要得到许多可能的方法来将数组划分为小的子数组。我们可以将阵列纵向和横向分开。我的算法很好,但是时间复杂度太差了。你能看看如何改进它吗

参数

nStart
-子数组的第一行

nEnd
-子数组的最后一行

mStart
mEnd
-用于第二维度(列)

check()
-函数检查结束条件

return
-不同数组分割方法的编号。我们在函数检查返回
true
时进行除法

public static long divide(int nStart, int nEnd, int mStart, int mEnd) {
    long result = 0;

    for(int i = 1; i < nEnd - nStart; i++) {
        if(check(nStart, nStart + i, mStart, mEnd) && check(nStart + i, nEnd, mStart, mEnd))
            result += divide(nStart, nStart + i, mStart, mEnd) * divide(nStart + i, nEnd, mStart, mEnd);
    }

    for(int i = 1; i < mEnd - mStart; i++) {
        if(check(nStart, nEnd, mStart, mStart + i) && check(nStart, nEnd, mStart + i, mEnd)) 
            result += divide(nStart, nEnd, mStart, mStart + i) * divide(nStart, nEnd, mStart + i, mEnd);
    }

    return (result == 0 ? 1 : result) % 1000000000; 
}

通过查看您的代码,我可以看到在递归的每个步骤中,您使用单个水平或垂直切割将二维数组划分为两个数组。然后验证这两个部分是否满足check方法定义的某些条件,如果满足,则将这两个部分放入递归中。当递归无法继续时,返回1。下面我假设你的算法总是产生你想要的结果

恐怕这个算法的有效优化在很大程度上取决于检查条件的作用。在平凡的情况下,当问题分解成一个简单的数学问题,可能有一个一般的非递归解时,它总是会重新出现。稍微复杂一点,但仍然可以有效解决的情况是,条件只检查数组的形状,这意味着例如check(1,5,1,4)将返回与check(3,7,5,8)相同的结果

当然,最复杂的是一般解决方案,其中检查条件可以是任何情况。在这种情况下,优化暴力解决方案所能做的不多,但我想到的一件事是为您的算法添加内存。您可以使用java.awt.Rectangle类(或创建您自己的类),该类将保存子数组的维度,然后使用java.util.HashMap来存储divide方法的执行结果,以便在使用相同参数再次调用该方法时参考。这将防止重复工作的发生

因此,您将haspmap定义为类中的静态变量:

static HashMap<Rectangle,Long> map = new HashMap<Rectangle,Long>();
然后将方法的结尾更改为以下形式:

result = (result == 0 ? 1 : result) % 1000000000;
map.put(r, result);
return result;
这将提高算法的性能


回到我之前的想法,如果检查条件足够简单,同样的优化可以更有效地完成。例如,如果您的检查条件仅检查数组的形状,则只需要将其宽度和高度作为贴图的键,这将减小贴图的大小并使其正点击数成倍增加。

在我看来,问题可以在不使用递归的情况下解决。您能否发布一些预期输出的示例输入?可能是2x2数组。请不要破坏您的帖子。请不要破坏您的帖子。它有投票权,所以人们认为它有价值。你能在你的描述中添加你的例子中暗示的附加限制吗?在我看来,
2x2
矩阵可以通过
4选择2+4选择3+4选择4=11
不同的方式进行垂直和水平细分。最坏的情况是当所有子数组的check返回true时。然后,此解决方案应精确计算数组的每个子数组的值一次。所以复杂性是可能的子数组的数量,我认为对于二维数组,它最多是O(n2),其中n是数组中的单元数。你确定吗?我们不应该考虑check()方法的迭代吗?它不会改变时间复杂度的等级吗?您可能是对的,但另一方面,大多数子数组都很小,并且没有或很少对小数组进行迭代。现在我对一维数组进行了精确计算(为了简单起见),发现迭代只增加了一个常数因子的复杂性。虽然一维数组有½(n2+n)个子数组,但我计算了复杂度,包括迭代次数为(2n2+5n+3),这比4大一倍,但仍然是O(n2)。当然,如果这也适用于二维阵列,那么它仍然应该通过计算进行验证。
Rectangle r = new Rectangle(nStart,mStart,nEnd,mEnd);
Long storedRes = map.get(r);
if (storedRes != null) {
    return storedRes;
}
result = (result == 0 ? 1 : result) % 1000000000;
map.put(r, result);
return result;