我希望得到一些帮助来评估以下算法复杂性的最佳方法(用伪代码编写):
Input N;
bool complete = false;
If(N Satisfies Condition A)
{
K = N/6;
For(int i = 1; i <= sqrt(K/6) && complete != true; i++)
{
If(K Satisfies Condition B based on i)
complete = true;
Else if(K Satisfies Condition C based on i)
complete = true;
Else if(K satisfies Condition D based on i)
complete = true;
Else if(K satisfies Condition E based on i)
{
If(K satisfies Condition D based on (i + 1))
{
Change Output;
complete = true;
}
Else
complete = true;
}
Else if(K satisfies Condition F based on i)
{
change output;
continue;
}
}
}
我熟悉大O-Notation,但(据我所知)最适用于最坏情况。但是,该算法很少遇到最坏情况(如果只满足条件F,则为O(sqrt(N)))。我不得不说至少有95%的输入N不符合最坏的情况。
通过在条件E中嵌入if语句,我发现了非常有趣的结果。一旦满足条件E,该程序基本上就完成了。它与常数O(1)非常接近,除了极少数条件F的情况。
例如:
N = 11, Time = 0.004 sec, Steps Taken = 0
N = 101, Time = 0.005 sec, Steps Taken = 1
N = 1001, Time = 0.004 sec, Steps Taken = 0
N = 10001, Time = 0.003 sec, Steps Taken = 1
N = 100001, Time = 0.004 sec, Steps Taken = 1
不要试图在那里寻找一个模式,看看一些随机和更大的值的结果:
N = 12764787846358441471, Time = 0.007, Steps Taken = 3332
N = 18446744073709551557, Time = 0.005, Steps Taken = 7
正如您所看到的,几乎所有时间都接近约0.006秒(在我的机器上),即使步骤不同,它也不会在任何方向上保持一致。这个算法是我为一篇正在研究的论文开发的算法,所以我不仅对大O符号开放来表示这个算法,我只是想用某种方式来事实地表示它的平均情况结果往往是非常很好。任何有关至少方向的见解都值得赞赏。我的数学知识远远超过了我迄今为止的CS知识,所以我对这种事物的接触很少。
谢谢, DevenJ
答案 0 :(得分:4)
您的算法的确定性是:
O(1)
在最好的情况下,O(sqrt(n))
。要查找平均运行时间,您必须在随机输入上运行算法,并绘制一个表示运行时或输入大小函数的步数的图表。然后你平滑你的点,试图让它们适合一个函数。通过绘制该图表,您会发现平均时间复杂度在平均情况下可能为O(1)
。