困惑的点——log,如何计算得出?
① 上限:用来表示该算法可能有的最高增长率。
② 大O表示法:如果某种算法的增长率上限(最差情况下)是f(n),那么说这种算法“在O(f(n))中”。n为输入规模。
上限的精确定义:对非负函数T(n),若存在两个正常数c和n0,对任意n>n0,有T(n)<cf(n),则称T(n)在集合O(f(n))中。
——T(n)表示算法的实际运行时间;
——f(n)是上限函数的一个表达式。
我们总是试图给算法的时间代价找到一个最“紧”(即最小)的上限,因此一般说顺序搜索法在O(n)中,而不是等于,因为也可以说它在O(n2)中。可以理解为O为上限的集合?
几个例子:
①
sum=0;
for(i=1;i<=n;i++)
sum+=n;
for循环执行,时间代价为O(n)。
②
sum=0;
for(i=1;i<=n;i++)
for(j=1;j<=i;j++)
sum+=n;
内层循环执行i次,外层执行n次,但是每一次内层循环的时间代价都因i的变化而不同。可以看到,第一次执行外层循环时i=1,第二次执行时i=2。每执行一次外层循环,i就以1的步长递增,直至最后一次i=n。因此,总的时间代价是从1累加到n,即 ,总运行时间为O(c3n2+c2n+c1),可化简为O(n2)。
③ 双重循环如排序,时间代价也为O(n2),只不过运行时间为第二个程序的两倍。上例中c3为1/2。
④
sum=0;
for (k=1;k<=n;k=k*2) //Do log n times;
for (j=1;j<=n;j++) // Do n times;
{
sum++;
}
内层循环执行次数恒为n。设外层循环执行次数为i,则循环结束时2i-1=n,i为logn,所以总时间代价为nlogn。
⑤
sum=0;
for (k=1;k<=n;k=k*2) //Do log n times;
for (j=1;j<=k;j++) // Do k times;
{
sum++;
}
外层循环同上,依旧是logn次,但内层循环次数为k,每次都随着外层循环变量k值的变化而变化。设外层循环执行第i次,则k=2i-1,即内层执行2i-1次。外层执行一次内层执行20次,外层执行两次内层21,一共执行20+21次,以此类推总的执行次数为 ,最终可化简为O(n)。
关于大O法可参考:https://blog.csdn.net/yuhk231/article/details/60099774