这个问题
如何求算法的时间复杂度?
我在发布一个关于SO的问题之前做了什么?
我经历了这个,这个,还有很多其他的环节
但是我没有找到一个关于如何计算时间复杂度的清晰而直接的解释。
我知道什么?
比如下面这样简单的代码:
char h = 'y'; // This will be executed 1 time
int abc = 0; // This will be executed 1 time
比如下面这样的循环:
for (int i = 0; i < N; i++) {
Console.Write('Hello World !');
}
int i=0;这将只执行一次。时间实际上计算为i=0
,而不是声明。
i<;N;这将执行N+1次
i++;这将执行N次
因此该循环所需的操作数为
{1+(n+1)+n}=2n+2
注意:这仍然可能是错误的,因为我对计算时间复杂度的理解并不自信
我想知道什么?
好的,这些小的基本计算,我想我知道,但在大多数情况下,我看到的时间复杂度是
O(N),O(n2),O(log N),O(N!)。。。和许多其他国家,
有没有人能帮我理解一个人是如何计算一个算法的时间复杂度的?我相信有很多像我一样的新手想知道这个。
如何求算法的时间复杂度
你把它将执行多少机器指令作为其输入大小的函数加起来,然后把表达式简化为最大(当N非常大时)项,并且可以包括任何简化常数因子。
例如,让我们看看如何简化2N+2
机器指令,将其描述为O(N)
。
为什么我们要删除两个2
s?
我们感兴趣的是当N变大时算法的性能。
考虑两个项2n和2。
当N变大时,这两个术语的相对影响是什么?假设N是一百万。
那么第一个期限是200万,第二个期限只有2个。
由于这个原因,我们删除了大N的最大项以外的所有项。
所以,现在我们已经从2n+2
到2n
。
传统上,我们只对不变因素的性能感兴趣。
这意味着,当N较大时,我们并不关心性能是否存在一定倍数的差异。无论如何,2n的单位在一开始就没有很好的定义。所以我们可以乘以或除以一个常数因子,得到最简单的表达式。
因此2n
就变成了n
。
这是一篇出色的文章:http://www.daniweb.com/software-development/computer-science/threads/13488/time-complexy-of-algorithm
下面的答案是从上面复制过来的(万一优秀的链接去半身不遂)
计算时间复杂度的最常用度量是大O表示法。这样就去掉了所有的常数因素,使得当N接近无穷大时,可以相对于N来估计运行时间。通常你可以这样想:
statement;
是常量。语句的运行时间不会相对于n发生变化。
for ( i = 0; i < N; i++ )
statement;
是线性的。循环的运行时间与N成正比,当N翻倍时,运行时间也是如此。
for ( i = 0; i < N; i++ ) {
for ( j = 0; j < N; j++ )
statement;
}
是二次的。两个环路的运行时间与N的平方成正比,当N倍增时,运行时间增加了N*N。
while ( low <= high ) {
mid = ( low + high ) / 2;
if ( target < list[mid] )
high = mid - 1;
else if ( target > list[mid] )
low = mid + 1;
else break;
}
是对数的。算法的运行时间与N可以除以2的次数成正比。这是因为算法每次迭代都会将工作区域一分为二。
void quicksort ( int list[], int left, int right )
{
int pivot = partition ( list, left, right );
quicksort ( list, left, pivot - 1 );
quicksort ( list, pivot + 1, right );
}
是N*log(N)。运行时间由N个循环(迭代或递归)组成,它们是对数的,因而该算法是线性和对数的结合。
一般情况下,用一个维度的每一个项目做一件事是线性的,用二维的每一个项目做一件事是二次的,把工作面积分成一半是对数的。还有其他的大O度量,比如三次,指数和平方根,但它们并不是那么常见。大O表示法被描述为O(
,其中
是度量值。快速排序算法可以描述为O(N*log(N))
。
请注意,所有这些都没有考虑到最佳,平均和最坏情况的度量。每个都有自己的大O符号。还要注意,这是一个非常简单化的解释。大O是最常见的,但它也比我所展示的更复杂。也有其他的记号,如大欧米茄,小o和大西塔。在算法分析课程之外,您可能不会遇到它们。;)
取自此处--算法时间复杂度介绍
在计算机科学中,算法的时间复杂度将算法运行所花费的时间量量化为表示输入的字符串长度的函数。
算法的时间复杂度通常用大O表示法表示,它不包括系数和低阶项。当以这种方式表示时,时间复杂度被说成是渐近地描述的,即,当输入大小变到无穷大时。
例如,如果一个算法在大小为n的所有输入上所需的时间至多为5n3+3n,则渐近时间复杂度为O(n3)。稍后会有更多的内容。
再举几个例子:
如果一个算法无论输入大小都需要相同的时间量,则称它在恒定时间内运行。
示例:
如果一个算法的时间执行与输入大小成正比,即时间随着输入大小的增加而线性增长,则称其在线性时间内运行。
考虑下面的例子,下面我在线性搜索一个元素,这具有O(n)的时间复杂度。
int find = 66;
var numbers = new int[] { 33, 435, 36, 37, 43, 45, 66, 656, 2232 };
for (int i = 0; i < numbers.Length - 1; i++)
{
if(find == numbers[i])
{
return;
}
}
更多示例:
如果一个算法的时间执行与输入大小的对数成正比,则称其在对数时间内运行。
示例:二进制搜索
回忆一下“二十个问题”游戏--任务是猜测一个区间中一个隐藏数字的值。每次你猜的时候,你都会被告知你的猜测是太高还是太低。二十个问题游戏暗示了一种策略,即利用你的猜测数字将间隔大小减半。这是被称为二分搜索的一般问题解决方法的一个例子
如果一个算法的时间执行与输入大小的平方成正比,则称其在二次时间内运行。
示例: