private static int Sum (int[] a, int from, int to){
int total=0;
for (int i=from; i <= to; i++)
res += a[i];
return total;
}
public static int Method3 (int []a){
int temp=0;
for (int i=0; i <= a.length; i++)
{
for (int j=0; j <= a.length; j++)
{
int c = Sum(a,i,j);
if (c%3 == 0)
{
if (j-i+1 > temp)
temp = j-i+1;
}
}
}
return temp;
}
Method3方法的目的是找到给定数组'的最长组合,以便组合数的总和可以除以3而没有余数。 我现在正试图弄清楚Method3方法的时间和内存复杂性,然后我的目的是学习如何将其提高到最大值。
我的假设是: Method3中的前两个循环导致O(n ^ 2)的时间复杂度,因为它是重复的 (n +(n-1)+ ... +1)次,等于[n(n + 1)] / 2 =&gt; (1/2)n ^ 2 +(1/2)n =&gt;为O(n ^ 2)。 但是,我们还有Sum方法,它嵌套在Method3的两个循环中,并且它的最坏情况复杂度只能是O(n) - 因为它是i和j之间最大可能的间隙(或者a.length in也就是说) 因此,我认为Method3的最终时间复杂度为:n ^ 2 * n = n ^ 3。是对的吗? 现在,关于内存复杂性,我真的很困惑。我的假设是它是O(1),因为在这个程序中只有整数变量,它包含一个字段。
现在接下来的问题是,如何提高效率?我怎么能接近这样的事情呢?最后,我怎么知道我所达到的复杂性是最好的?
谢谢!
答案 0 :(得分:0)
是的,时间复杂度为O(n ^ 3)。 是的,空间复杂度是O(1)。唯一使用的空间是指数的常数。
使您的算法更有效并缩短比较量的一种方法是反转内部循环。现在,你基本上检查i和j的每个可能的组合。例如,对于索引1,2,3,4,您将检查1-2,1-3,1-4,2-3,2-4,3-4。
相反,您可以从 j = a.length() - 1 开始。这样,你开始与你当前的'最长的组合'。一旦组合起作用(意味着如果组合满足Sum(1,i,j)%3 == 0要求),则不必检查所有其他j值,并且您可以跳转到下一个i值。
你的Sum方法很好。
编辑:
结果仍然是O(n ^ 3)最坏情况时间复杂度。但实际上,它是否可能使您的代码更快?当然是) 由于你有三次迭代,最坏的情况总是N ^ 3。