【字幕】恋上数据结构与算法之07复杂度02斐波那契数列

视频地址:07复杂度02斐波那契数列_哔哩哔哩_bilibili

来我们看一下我们的第一个PPT叫做复杂度,PPT我们都会给的,上完课我们就给好吧?来首先我们看第一个问题,什么是算法?算法其实很简单,算法其实就是用于解决特定问题的一系列的执行步骤,比如说像这个代码,其实这一句你也可以称之为算法,这个加号这个加法你可以叫算法对吧?因为它因为它解决了什么问题,解决了这个加法这个运算对吧?

还有这个代码,这个代码也可以称之为是算法,就为什么?因为它解决了什么问题?解决了计算1+2+3一直加到n你看这个代码不就是从1+2+3一直加到n吗对吧?所以这两个其实我们可以都称之为是算法,其实这其实不能说唉一一说到算法就是非常复杂,不是算法其实就是你能解决问题就可以了。

那这个小到一行代码多到这个上万行代码其实都叫算法对吧?让我们使用不同的算法来解决同一个问题的话,有时候效率可能会相差非常大,因为我们都知道有时候我们解决一个问题,真的方法很多对吧?算法很多,但是用不同的算法效率真的是可能会非常大,比如说我们举个例子求第n个菲波纳契数,菲波纳契number啊这个东西,那菲波纳契数这个东西是什么意思呢?

我们来看一下吧,来我们这里是复杂度,然后我们在这个位置呢我们右击一下,我们新建一个我们的这个类,这个类的名称呢你可以自己随便起,只不过我自己故意起成叫闷啊,你你叫什么ABC也可以随便你。

然后com点mj啊我们起一个报名,然后这个位置有个勾选闷方法,只要我们一勾选的话,它就会自动帮我们生成慢方法,我们就直接在这个位置写代码就可以了。

比如说我们打印一下,刚刚说到是不是用sister点out你喷请烂是吧?其实他可以有个缩写叫sy so你看我直接翘syso它就有个提示,这个是敲回车,这个打印就出来了,比如说我们打印一个123,那这个时候我们右击跑一下啊,都是很简单的,没什么好说的。

好,我们在这个位置啊,我们在这个位置来测试一下什么呢?这个菲薄纳粹术,那什么叫菲薄纳粹术呢?我们来看一下。

是这样的,比如说我们假设最前面这个数是0,然后第二个数呢是一,那下面这个数呢就是前面两个数相加,那0+1是多少?一,那下一个数呢又是前面两个数相加,1+1是多少?2,那下一个数呢又是前面两个数相加,那就是三,那2+3是多少?53+5是多少?85+8是多少?13对吧?等等,就这样,这个东西呢叫做菲波纳契数。

那这个菲波纳系数假设我要求你去求什么?去求第n个第n个啊?菲波纳粹数。

比如说我们的这个n呢是0,那你返回的应该就是0,我们n是1,你返回是一,n是2就返回它,n是3,m是4,n是5,就求第n个斐波那契数,那这个东西怎么去求呢?我们很多种方法,呃菲伯纳县呢它英文单词是这个啊我们就用fabfabn好,我们看一下这个东西怎么求的,这个东西咋求呢?

其实很多种方法这个方法非常多对吧?

我这里介绍两种两种,一种呢是通过递归的形式,怎么递归的形式呢?大家思考一下,你求第n项不就是n加一项跟n呃应该说噢你求第n项不就是n减一项,还有n减二项相加吗?

所以这个位置我们可以直接来一个fibn-1加 fibn-2,大家思考一下,是不是就是这样子?

你求第n项那不就是n减一项加上n减二项嘛,对吧?这样不就可以了吗?啊但是这里有个问题,对吧?你这样的话怎么样死循环,是不是死循环了?你fib调fibfib又调fib对吧?一直掉是死循环,那怎么办呢?

那前面两个其实我们是要把它剔除掉了,如果n小于等于一,我们直接返回n不就好了吗?大家想想是不是?它如果传0我就返回0,如果传一我就返回一,那不就符合前面两个了吗?那你这个n一旦大于一,一旦大于一,也就是后面的这些是吧?那就是前面两个开始相交,我们这样写就可以了。对吧?

这样写就比较简洁了,好,这个是一种做法,那我们看一下是否能解决我们的问题啊。Sy Esso反映一下,那这个时候我们直接fib我们把零传进去,然后把前面几个都传进去,34对吧?我们看一下对不对?我们看一下打印的结果是01123。没错,是他们对吧?然后我们再再往下写,再验证一个啊,来跑一下。呃1235没有问题对吧?说明我们这个是没有问题的,这是一种方法这一种方法。

噢但是这个家伙呢其实是有一点性能问题的,有点性能问题的,那什么性能问题呢?

我们来看一下,现在我们尝试这样子把这个东西呢写大一点,把这个东西写大一点,fib比如说写个19,我们看有没有问题?一样,唉还是算的挺快的是吧?然后来个30点一下感觉还是挺快的是吧?那么这个时候我们再来一个试试点一下。唉也是挺快的,对吧?再来个64。

好,注意看,我输入64这个结果迟迟没有出来,大家可以想象一下,这个64挺小的吧,我就是想求第六十四个字而言,第六十四个结果是什么对吧?

那你看他出不来了,而且你看这里这个红色就代表这个程序正在运行,除非我点击它,那现在我一点击它对吧?这个程序就关了,那说明什么?说明这个算法是有问题的,那为什么这个算法有问题呢?这个等会我会给大家分析,大家不用着急好吧,说明我们这个算法是有问题的。

那接下来我们换一种算法,接下来我们换一种算法,这个是一这个是二好吧?然后我们这里这样子,然后这应该是一应该是1,然后我们这里呢调用我们的这个fib2,然后把这个64传给这一次我们是直接穿这个64,我们来对比一下,那这个东西怎么做呢?还是一样的,这个条件我们就这么写,就是如果你传的是小于等于一,我我就直接反问a没有问题,那这怎么做呢?

这个很简单,其实我们看一下这个规律啊,你的这一项不就前面两个数相加吗?那我们就完全可以这么做,因为我们这个n呢怎么样?它它能来到这里啊,它代码能来到这里,说明肯定是大于一的,也就是从这里开始,所以前面两个数我们假设它已经存在了啊是吧?因为你是从这里开始算的,所以这个时候我们可以这样做。

第一个数是0,s1c20第二个数是1,对吧?这个就代表这两个就代表前面两个,因为前面前面两个已经被我们这个用这个排除了嘛,所以能来到这里说明是从这里开始算。

那这个时候怎么做呢?这个时候应该是写一个后循环对吧?那这个东西需要循环多少次呢?需要循环多少次呢?我们来看一下,也就是说我们这个东西需要加多少次?比如说我们要求这一项是不是这个家伙相加要等于它,而这个家伙相加然后等于他,而这个家伙相加等于他。是不是一直到我们这个地方?

那我传的是第n项,那前面要加多少次呢?这个我们怎么算?比如说举个例子,这个是n等于0,这个是n等于1,就是n等于2,就是n等于3,就是n等于4,就是n=5,对吧?

你思考一下,如果我们是n等于2的话,前面两个是不是只需要加一次就来到这里啊?如果我们n是等于三的话,是不是得加两次啊?先0+1要等于它,然后再1+1等于它是不是加两次啊?所以我们这个要加多少次?N减一次,没错,要加n减一次,所以这个应该是小于 n减一,这应该小于n减一对吧,这个就非常简单,非常简单。

好,那怎么去加呢?首先我们每次加每次加肯定都是前面两个数,也就是这两个数相加,所以是first加我们的这个CK对不对?好,那加完之后呢,这两个加完之后我们要干什么?啊这两个加完大家思考一下,这两个加完了结果是不是得放到这个位置来要?

下一次的时候它们两个相加,说白了,这两个相加的结果要给下一次的second,你思考一下,下次相加的话这个是first,这个是second,说白了我们两个相加的结果要给下一次的second,我这样说能不能听懂这两个相加的结果要给下一次相加的第二个数,所以很简单,Seda second,SEC on the second,其实就是这样给。

然后second这个值赋值之前你想一下,你本来你本来上一次结果的第二个数,是不是应该给下一次的第一个数?所以first应该是这样就可以了。但是这两句代码不能交换,因为你萨姆把second付掉了,那second是不是就是被覆盖了?所以应该是second先把自己的值给下一次的第一个数,然后再把和给下一次的第二个数搞定。

好,那这个时候我们直接返回谁?同学们请问最后的结果在谁手里?肯定是second手里,是不是?最后结果肯定在section手里,好,同学们我们算法搞定。

那这个时候我们试一下算60次,这个时候我们直接点一下,你看马上算出来了,注意看马上算出来了。那么这个时候我们再往下算,比如说算一个70.1下秒算,看到吗?秒算,对不对噢?但是我们使用fibe这个家伙就不行。Fibe我们当写64的时候,他几乎已经算不出来了,对不对?对吧?那这是为什么呢?这个等会我会给大家分析。

总之我们先清楚地认识到一个问题,什么问题呢?就是我们解决同一个问题呢将来可能有不同的算法,但是使用不同的算法去解决这个问题的话,可能效率相差非常大,真的是相差非常非常之大,对吧?

好,那这两个相差有多大呢?这样子我们可以用一种方法去做,什么方法呢?测量一下他们这个家伙计算啊计算这个结果所耗的时间对吧?比如说这个家伙算算这个结果花了是这个10秒钟,那这个花的是一秒钟,那明显他好嘛,这是一种方法对吧?我们可以尝试这种方法来做一下吧啊那怎么做呢这样子啊。

为了节省时间,我这里就直接拿出一个我自己写好的一个小工具啊小工具啊用测量实际那个小工具很简单一个东西,大家可以自己客户看一下我怎么写的代码也比较简单噢。

呃在哪个位置呢?在这个位置我这有个time to,我把它直接拷过来。

非常简单的,就是开始什么时候开始,什么时候结束,中间号是多少,非常简单,同学们可以自己去看啊,我就不浪费那时间,浪费时间去写了,那怎么做呢?很简单,我这个贪图这么用,直接汤姆兔这里有个东西叫做check检查,然后你给我一个标题,这个标题呢你就自己写嘛,比如说这个标题叫fab一,然后再来个fab二,就是我测两个东西对吧?然后这里传什么呢?

这个这里要求是传一个task,对象我们直接你有一个task就可以了,你有一个task,那我们这里有一个task好,另一个task的话这里报错是因为要导入一个东西,因为导入的东西啊,因为我这里面有个东西叫做这个task,你要导入一下,这个东西啊怎么导入呢?我们按一下CTRL加一就会自动去导入,你看input对吧?导入应该导入它啊导入就可以用了,那这是什么东西啊?这个是Java的一个内匿匿名类啊匿名对象匿名对象匿名类,然后你只需要将你需要测试的代码写在这个地方就可以了,好吧?

测试代码写在这个地方就可以了,比如说我们在这个位置直接来一个什么呢?C等2fib1,然后这里比如说我们传一个这个30,好,那这个也是一样的,我直接拷贝一下 fib2这ffib2g看到也就是说将来呢你只需要将你你需要测试的代码写在这个sq里面就可以了,写在这个sq里面就可以了,你看我现在是测这个家测这个啊,这个时候我们直接把这个程序跑一下啊看一下啊,直接我们又击。

好,可以看到它们之间的这个时间差距怎么样呢?呃fibe它花的是0.007,对吧?要这个呢几乎为0,几乎为0啊,那这个时候我们再把这个数字呢再写大一点,好吧?35,然后这里传一个35,好,这里传一个35好吧,大家传的是一样的,可以看到0.043这个几乎为0,然后我们再写个445。

好,他开始有点慢了知道吧?Fib1开始有点慢了,可以看看到5:00:08,五点八秒,然后这个呢0秒,也就是说我们写的第二个算法,随着数字的这个增大,几乎怎么样?时间更改不是很大,对吧?但是这个fibe呢怎么样?这个时间就慢慢慢慢增加了,对吧?

我们再测一个啊,比如说就46啊,46好吧,46,我们再运行一遍,我们看一下你看9.440对不对?独者程啊,多线程我看一下啊,我里面应该是没有去写多线程的东西,应该是没有写,我看一下噢斯代利克CC卡了。

应该是不影响不影响,因为我这个是静态方法,静态方法多线程应该是没什么影响,没影响啊,就是你多线程也可以用啊,我这个是静态方法,我们来看一下,你看这个是9秒对吧?这个是什么?这个是0秒对不对?那这个这个差距真的是非常大。

那这个时候我们再看一下,我把它这个东西给注释掉,啊这里我写大一点对吧?比如说我写个98,你看零秒对吧?不过98呢应该这个结果你看已经变成负了,那说明什么?说明已经超过这个整数的范围了,这个不够我们不用管,我们关心的就是这个数字不管怎么大,你看它所耗的时间很短很短啊。

好,这个呢就是通过什么?通过一个这个检查他们的时间来比较一下这两个算法的性能怎么样,那从时间这个维度去看的话,那说明这个算法是有问题的,那为什么它有问题呢?

会我们会去分析到,所以有一个问题就摆在我们面前,什么面前呢?就是我们在解决一个问题的时候,如果用了不同的算法,那么怎么去评价一个算法好还是坏呢?怎么去评判呢?对吧?比如说我们从这个代码上看能不能一眼看出来,比如说这个代码好,这个代码坏能不能看出来呢?这个就是我们要去研究的一个问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值