算法图解1-二分法与大O表示法
Posted /少司命
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法图解1-二分法与大O表示法相关的知识,希望对你有一定的参考价值。
目录
一,二分法与大O表示法
1.1写在前面
从今天开始,我将开始更新算法图解入门,也是自己在不断的学习中总结经验,感兴趣的可以点个关注,有时间就会更新算法相关的知识点,可能在十天内就可以完成更新,你的每一个点赞和收藏都是我最大的动力。文字和图片内容部分参考《算法图解》这本书。
1.2需要具备的知识
要学会算法,需要具备基本的代数知识。具体地说,给定函数f(x) = x*2,f(5)的值是多少?如果你的答案是10,那就够了。
另外,如果你熟悉一门编程语言,算法将会更容易理解,你可以选择C语言,也可以选择Python,也可以是其他语言。
1.3二分法
假设要在电话簿中找一个名字以K打头的人, (现在谁还用电话簿!)可以从头开始翻页,直到进入以K打头的部分。但你很可能不这样做,而是从中间开始,因为你知道以K打头的名字在电话簿中间。
又假设要在字典中找一个以S打头的单词,你也将从中间附近开始.现在假设你登录QQ当你这样做时, QQ必须核实你是否有其网站的账户,因此必须在其数据库中查找你的用户名。如果你的用户名为karlmageddon, QQ可从以A打头的部分开始查找,但更合乎逻辑的做法是从中间开始查找。
这是一个查找问题,在前述所有情况下,都可使用同一种算法来解决问题,这种算法就是二分查找。
下面举一个例子说明二分查找的工作原理,我随便想一个1~100的数字
你的目标是以最少的次数找到该数字。你每次猜测后,我会说小了,大了或者对了。
这是简单查找,更准确的应该是傻找,每次猜测只能排除一个数字。如果我想找99,要猜99次才能得到结果。
1.4更佳的查找方式
从50开始,每次判断与50的大小,没有猜对,但排除了一半的数字,猜75,大了,将余下的数字排除一半,一直猜,最后猜到了53.
这是二分查找,是我们学习的第一种算法!每次猜测的数字如下,100个元素最多用7步。
如果查找的单词位于字典的末尾,使用简单查找要240000步,用二分查找是最多用18步。
1.4.1代码设计
给定一个数组arr[] = {1,2,3,4,5,6,7,8,9} 刚开始给定 left = 1, right = 9 , 那么mid = 5
例如要找的是3,3在mid的左边,那么让left向右走一步(left++),这时候right也得重新给 (right = mid -1),再重新计算mid值,如果还是没找到继续重复步骤直至找到为止。
int main()
{
int n = 0;
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sz = sizeof(arr) / sizeof(arr[0]);//求数组个数
scanf("%d", &n);//输入要找的数
int getchar();
int left = 0;
int right = sz - 1;
while (left < right)
{
int mid = (left + right) / 2;
if (n < arr[mid])
{
right = mid - 1;
}
else if (n>arr[mid])
{
left = mid + 1;
}
else
{
printf("找到了是: %d\\n", mid);
break;
}
}
if (left > right)
{
printf("找不到了");
}
return 0;
}
1.4.2运行时间
每次介绍算法时,我都将讨论其运行时间。一般而言,应选择效率最高的算法,以最大限度地减少运行时间或占用空间。
回到前面的二分查找。使用它可节省多少时间呢?简单查找逐个地检查数字,如果列表包含100个数字,最多需要猜100次。如果列表包含40亿个数字,最多需要猜40亿次。换言之,最多需要猜测的次数与列表长度相同,这被称为线性时间 (linear time)。
二分查找则不同。如果列表包含100个元素,最多要猜7次;如果列表包含40亿个数字,最多需猜32次。厉害吧?二分查找的运行时间为对数时间(或log时间)。下表总结了我们发现的情况。
1.5大O表示法
大O表示法是一种特殊的表示方法,指出了算法的速度有多快。
1.5.1算法的运行时间以不同的速度增加
Bob要为NASA编写一个查找算法,这个算法在火箭即将登陆月球前开始执行,帮助计算着陆地点。
这个示例表明,两种算法的运行时间呈现不同的增速。Bob需要做出决定,是使用简单查找还是二分查找。使用的算法必须快速而准确。
一方面,二分查找的速度更快。Bob必须在10秒钟内找出着陆地点,否则火箭将偏离方向。另一方面,简单查找算法编写起来更容易,因此出现bug的可能性更小。Bob可不希望引导火箭着陆的代码中有bug!为确保万无一失, Bob决定计算两种算法在列表包含100个元素的情况下需要的时间。
假设检查一个元素需要1毫秒。使用简单查找时, Bob必须检查100个元素,因此需要100毫秒才能查找完毕。而使用二分查找时,只需检查7个元素(l0g2100大约为7),因此需要7毫秒就能查找完毕。然而,实际要查找的列表可能包含10亿个元素,在这种情况下,简单查找需要多长时间呢?二分查找又需要多长时间呢?请务必找出这两个问题的答案,再接着往下读。
Bob使用包含10亿个元素的列表运行二分查找,运行时间为30毫秒( 1og 1 000 000 000约为30),他心里想,二分查找的速度大约为简单查找的15倍,因为列表包含100个元素时,简单查找需要100毫秒,而二分查找需要7毫秒。因此,列表包含10亿个元素时,简单查找需要30 x 15=450毫秒,完全符合在10秒内查找完毕的要求。Bob决定使用简单查找。这是正确的选择吗?
不是。实际上, Bob错了,而且错得离谱。列表包含10亿个元素时,简单查找需要10亿毫秒相当于11天!为什么会这样呢?因为二分查找和简单查找的运行时间的增速不同。也就是说,随着元素的增加,二分法所查找的额外时间并不多。
1.5.2大O表示法指出了最糟糕情况夏下的运行时间
假设你使用简单查找在电话簿中找人。你知道,简单查找的运行时间为O(n),这意味着在最糟糕情况下,必须查看电话簿中的每个条目。如果要查找的是Adit-电话簿中的第一个人,一次就能找到,无需查看每个条目。考虑到一次就找到了Adit,请问这种算法的运行时间是O(n)还是O(1)呢?
简单查找的运行时间总是为(n)。在找Adi时,一次就找到了,这是最佳的情形,但大O表示法说的是最糟的情形。因此,你可以说,在最糟情况下,必须查看电话簿中的每个条目,对应的运行时间为O(n),这是一个保证--你知道简单查找的运行时间不可能超过O(n)。
1.5.3一些常见的大O运行时间
下面按从快到慢的顺序列出了你经常会遇到的5种大O运行时间。
1,O(log n),也叫对数时间,这样的算法包括二分查找。
2,O(n),也叫线性时间,这样的算法包括简单查找。
3,O(n * log n),这样的算法是快速排序--一种速度较快的排序算法。
4,O(n^2)这样的算法是选择排序--种速度较慢的排序算法。
5,O(n!),这样的算法包括接下来将介绍的旅行商问题的解决方案-种非常慢的算法。
假设你要绘制一个包含16格的网格,且有5种不同的算法可供选择,这些算法的运行时间如上所示。如果你选择第一种算法,绘制该网格所需的操作数将为4 ( log 16=4),。假设你每秒可执行10次操作,那么绘制该网格需要0.4秒。如果要绘制一个包含1024格的网格呢?这需要执行10( log 1024 = 10 )次操作,换言之,绘制这样的网格需要1秒。这是使用第一种算法的情况。
第二种算法更慢,其运行时间为O(n)。即要绘制16个格子,需要执行16次操作;要绘制1024个格子,需要执行1024次操作。执行这些操作需要多少秒呢?
从图中我可以得到启示
1,算法的速度并非指的是时间,而是操作数的增长速度。
2,谈论算法速度时,我们说的是随着输入的增加,其运行时间将以怎样的速度增加。
3,算法的运行时间用大O表示法表示。
以上是关于算法图解1-二分法与大O表示法的主要内容,如果未能解决你的问题,请参考以下文章