七月在线公开课笔记-三十七-
七月在线公开课笔记(三十七)
人工智能—面试求职公开课(七月在线出品) - P16:应届毕业生的面试历程 - 七月在线-julyedu - BV1Xf4y1r74s
可能也就是我自己的一些经历吧,还有一些嗯。是。面试过过程中踩的一些坑吧,然后也是和大家分享一下。就我觉得这个面试呃一面是你的能力和实力,还有一些运气。然后当然还有一部分就是你。
了解不了解了解一些套路什么的。今年收维港贼难贼难真难。那我们就开始吧,好吧。Oh。嗯,首先做一个简单的自我介绍,就这道这这这里大家都这个叫ricky,然后。目前的话我是就读于某C9高校。
然后机械专业的硕士。我想大家已经能猜到是哪哪哪两所学校了,好吧,然后我今天就会做一些简单的自我介绍,然后一。😊,就是自己在求招过程中的一些感悟吧。还有就是我提供的面试经验的一些分享。
然后接下来就是结合自己在面试过程中的一些经历,还有踩了一些坑,给大家提点建议,也希望能帮助到大家到后面的求职过程中去比较顺利一点吧,好吧。然后就是我我其实是机械专业的,然后在转算算返岗之前的话。
就会一点简单的C加加。然后然后其他的都不会知道吗?我连数据结构这些啥都不懂,然后自己就自学过一段时间,看过一点西瓜书和花书嘛。但是其实自己看的话也是看到一知半解吧。我这样前前后后大概折腾了将近两个月吧。
也没学到啥啥的啥东西,就挺迷茫的,觉得自己可能转不了了或者什么样的。然后一个偶然的机会吧,然后就刚好就了解到7月这边吧。然后我当时其实刚开始也不知道,然后就往在网上查了一查,然后刚好我身边有一个同学。
他报了一个就是学这边的一个嗯推荐班,好像推就是推推荐系统的一个班,好像嗯,他说老师讲的还不错,就当时也是抱着试一试吧,人民币,因为我是秋招嘛,当时已经是45月份了,如果再不好好准备的话,可能就来不及了。
那其实我也没准备多久,因为中中间还有个中期耽误了嘛。然后就是这样一个情况,就最开始是自学的,但是其实效果也不好。然后的话就是然后去区月这边的话也是。其实帮到我挺多的。
我感觉就是说我在呃交绍过程中明明显感觉到就是说在面试的过程中碰到一些基础的一些机极学习和深度学习的东西的话,真的很多就是就是上课的时候讲过的东西。而且比如说我记面oppo的时候,他让我那个首推SVM。
就你给一张纸,你从最开始的你那个分类,然后到最后的被后找找出那个最宽的最后那个分界面,这些一一步一步推下来的。然后一直到最后的那个怎么去通过SMO算法,这些去求这些东西都是一步一步推下来的。
我觉得这个是比较好的,就是说他会这边讲的比较细一点。呃,然后的话就是秋招的感悟期,我觉得就是菜。就是你如果太菜的话,你找工作会很累很累很累。嗯,我身边的很多同学还比较厉害的,就offer特别大特别多。
然后也因为我是一个就是转过来的嘛,非科班嘛,就是说中间也踩了很多坑,你知道吗?所以觉得真的是深刻有体会,才是原罪。所以大家在面试的过程中以及面试之前不要抱什么侥幸心理。最好就是去夯实自己的基础。
就是让自己变得更好。当然面试过程中也有一些技巧,我后面会说到具体的举几个例子去和大家说一下。但是我觉得要转转算法的话,最重要的是两个点,一是你要转到。
现在很多算法呢都要求有机器学习有深度学习的经验或项目经验或者是一些基础啊什么的。其实最重要的就是一些呃计算机专业比较就是最开始最基本的东西就是数据结构这些,还有你要精通一门语言。
但是很多其实他没有要求你特定的是哪些。其实我知道的C加加和pyython好像都可以。java的话好像更多是做后端算法里面,我听到的比较少一点。就是这样一个情况。然后所以说大家要找算发展的话,呃。
就是数据结构这块一定要。掌握的比较好一点,然后接着接下来就是刷题去做一些算法题。因为很多算法题他面试或就是公司在面试过程中都会有这些题的这是比较重要的。一定要夯实自己的基础,然后再去找。不然的话。
你就会受受打击。然后的话就接下来就是这几个点,就是首先第一个是你要静下心来去好好的沉淀你自己,你自己就是说要去提高一下自己。比如说我觉得最重要的就是比如说你需要算法的,你数据结构,什么是对什么是站。
什么是链表,什么是双向链表,并且你一定要。就是掌握的很很清很清楚吧。不然的话,你肯定我觉得你面试很大程度上在首次代码,这块你就挂了。因为很多公司他会有都会有这个环节去首次代码。明白吗?然后的话呃。对。
面CV他他当时最后最后让我首推了SVM就是因为他最后讲完之后,他看我简历上写了我用过S我的那个CV里面有一点是涉及到SVM就去做一些处理的。他就问我了了了解了解M我就了解因为我简历上也写了。
就是熟悉SVM算法什么些算法我推SM样的情况然后的话就是接下来最重要的就是你要及时的掌握一些招聘信息。因为我觉得实力是一部分,然后机会机遇也是一部分有有些公司他宣传的没有那么到位,或者说知道人不多。
大家就没有投这个公司这公司投的人比较少的话,他面试的过程中因为他每年肯定要招一定的人啊,但是你不太就是说这相这些你是特特特别的情况下在这些人里他可能会难度没有那么大就说就是各方面的消息你要去掌握就说你客上的一些内推这些最好时就招的时候每天都会去刷样。
7月这边有一些内推,也可以去了解一下。那就是一个信息,就是说自己的服求世界了。呃,在某个公司上班的或者什么也可以找他们内推一下,或了解一些信息。其实最主要的。
我今年求招过程中觉得自己吃亏了一点就是没有去实习,就是非常实习真的非常非常非常非常重要。我当时呃76月多7月份的时候找到了华为的实习,知道吗?但是我导师不让我去。
我当时就找好那边主管也给我打电话问我可不可以过去。然后我我我当时挺想去的,但是就是这个东西肯定要我们实验室管的比较严一点。我就去和导师沟通。他说导师不同意,你知道吗?所以就没有去,导致在求招过程中。
可能就相对吃亏一点吧。所以说如果你有嗯一些大厂的实习的经历或什么的。这是非常重要的。就是当然如果说是你不是这这一季找找工作,下季的话,你提前去大厂实习的话也挺好的。后面去找工作了什么的。
都相对比较有把握一点。然后的话至实秋招的过程中的话,其实6到8月份是一个节点。我感觉8月份到10月份又是一个节点,6到8月份基本上都是那种神仙打架,大家都很厉害。
然后跟你受过各种各样的提前PSPoffer什么的。然后真的很难很难,就提前批的时候。但是提验T验P厉害的人多,但是有个问题就是。他很多人都没有很好的准备。面试的难度也相对于低一点。
我感觉因为我之前我们实验室有个同学就去就就要是vivo。啊,求找了那个提前批的给嘛。比较简单,他说当时面试面都比较简单一点。那当然其实唯有面试总体比较简单一点,但是相比那个秋招的话。
正式秋招的话可能更能容易一点。就也是考虑。然后8月份份到10月份的话,就是正式的基本开始秋招了。就我我说这些相对于一些互联网公司,还有一些比较大的一些公司。因为再往后的话就有一些小的公司。
当然有想去银行这些做办法什么的,也也可以考虑,这些都相对比较晚一点。所以说最重要的还是自己的硬实力,硬实力一定要高。然后接下来就是掌握一些信息。这是我我我自己觉得的一些东西。然。
接下来的话我就分享一下重点分享几个自己的面试过程的一些经验,好吧。我主要我就从讲一下这四个公司吧,好吧。呃,冲招。冲超。呃,说实话不好不好去评判。呃,冲招的话有时候他会看,我觉得看。
这个因为今年算法岗本来就难,再冲招的话,我觉得可能。也不敢说没有,但是可能就更难一点。我觉得。就除非说有的人特别厉害,他拿了很多很多offer,然后他会在呃就去招会计书的时候,放弃很多公司的。
然后这个公司又没有去补录或什么他会功能名额比较多一点。但是这种情况下一般不会发生在大公司特别厉害的公司。那是中小型公司。对。这个。其是是这样一个情况。但是我觉得你如果觉得自己秋饶找的不是特别满意的话。
也可以再去试一下冲超也是可以的。我觉得。对。然后我接下来就说一下主要面试的这几个公司吧。然后第一个就是个通科技,我面的这个公司呃,总共面了两面,哦反正一般就是两面,两面技术面,第三个是HR面。
我很尴尬的是在第二面总监面,就应该是主管面的时候,最后最后的算代码题上,我死了。因为我是给科班,他出了一个题,还相对比较难一点。我刚我光看题议就看了将近一分钟吧,才看懂。我简单给他说了一下我的思路。呃。
他可能觉得我也说的思路。嗯,知道吧?时间也就时间复杂度太高了,也没让我写。然后就简单跟我说一下怎么样去优化,然后就结束了。因为葱的话面主要是。这样一个情况,他会第一面试他会让你去讲一下自己的项目。
然后针对自己的项目里面的东西去问,问问的是真的真的特别细。他会从具体的在哪里放的,那面都有什么参数了什么的,或者说软了这些都会问的很很细。
然后以及度爆炸这些都都会神经网络里面涉及的很多点 batch些都会问。然后他最后还问了我一个问题,我就我也没白是C嘛,他最后问我一个类。哦,他说你怎么去区分呃。
就是那先他向我们讲了一下什么是聚类是什么样的,然后让我讲了一下怎么去区分聚类是否完成了。哎,特别巧的是,当时在这边7月这边上课的时候,那个哎小杨老师讲过啊,我也就嗯了了解一点。然后的话他也一面的时候。
最后问了我一个算法,题实一个类似于孔排序的一个问题。就是说哦有100个同学,他们的成绩是什么的,然后你对这成绩进行排序什么的,大概就这样一个过程。我刚好也看过类似的,就是说。啊写了一下。对。
所以说就是算法题很重要。他们每个每每个基本上都会有都会有一个算法题,要大家去写。然后一面面的还挺那啥的,呃,挺挺好的吧,挺挺顺挺顺利的。然后面面说完和我联系聊了也挺好的。然后完了之后。
我就给他就我给大家提个建议,就是说面面试的过程中嗯。不管是面对哪家公司面完之后,就是简单问问一下,咨询一下面试官是主要做哪一方面的工作的。然后可以借这个机会和面试官多聊几句。然后的话。
如果你对他做那个方向比较稍微也懂一点的话,还是个比较好比较好的机会。其次就是说一定要让面试官给你提点提提几点建议,你从他给你提建议的过程中,你就能大大概把握到你自己这次面试怎么样。
他对你的感觉是什么样的。但是千万不要直接问人家面试官,你觉得我怎么样,你觉得我能不能过什么,不要太傻了。你会问的面试官很尴尬,他不知道怎么回答你明白了吗?他即使你过了,他很多面试官也不会直接告诉你。
你过了,即使你没过,他也不会直接说的。就是说通过他给你提的建议,就就你给大概可以了解到。结果云聪云聪的一面面试官,他就跟我说啊,我觉得挺好的,算不上他谈谈不上什么建议吧。
就是说你们在学校做的项目可能和企业的项目还是有啥点差别的。怎么怎么说企业的项目可能涉及的面更广啊,什么,他就我这样说了一下,当说完我我其实感觉大概就心里还觉得还还可以吧,但是也不敢保证。然后面完。
那天下午然后我一点多面的,然后下午4点多就给我发的短信,说约二面,约的是第二天的。然后二面的时候就比较那啥一点,那面时会比较高冷一点,一进来就让我讲讲项目,项目讲完之后就问了我三四个简单的问题。
就会问了我,他说你你用的啥。嗯,放假,我说我那个天。啊,他说那你了解深呃ten the floor吗?说具简单看过一点点,他说那你对那个底层的框架了解吗?是啥的?我当时又懵逼了,因为我首先我是飞鸽班的。
我也没有挖那么深。我觉得可能大多数人挖不到挖不了那么深吧,然后我就。就感觉挺不好的。然后最后他又问了我一个,我用的是啥东西,服我用服务器是啥,还是这些就问了我一些这些。然后最后就是直接给我写了一个题。
一算法题。其实我觉得更多的是项目也也有可能是我的项目太简单了,人家问的问题比较少一点,我觉得是也也也有这个可能,但是算法提升的很重要,里面的这些。第二个oppo也是这样的,就都有算法题。
oppo问的特别特别细。他会问我很多。就是说呃我当时面的时候,因为我项目里面有写那他项目讲完之后,他就问我说嗯对常用的就是神经网络你都了解吗?里exnet什么,你知道吗?
后glenet什么你知道吗net知道什么什么sonnet我从第一个也幸亏我之前复习过看过。然后我从第一个从就是应该不是说第一调。
就是说现在还偶尔在用的alexnet也直讲到了sonnet就里面关键的一点什么的就跟人家讲了一下,面试完还说觉得还还可以,也是因为最后我当时我其实这列表那当时面试的时候一一直有不是特别懂我懂一。
当时让我写了一个。呃,好像是环形列表,然后让我就是插入一个数,然后去判断那啥。我当时。就是几分钟,他说我们面试间就40540分钟,他说我写我我当时是没写完,你知道吗?然后自己当时脑子也有点闷。
然后这个题句话,就之前面的其实讲到一些东西还可以,就是一学习和深度学习的东西。然后我就会问他,我说你给我提点建议吧,他给我说,他说呃。我觉得你这块如果你以后做CV的话,你应该你基本上没啥问题了。
就CV就算吧这块。但是你的呃基本基础的数据结构和呃代码这块,我觉得你还是有有点问题的。怎么做?我一听这句话,我就叫我凉凉了。果不其然没有过,最后就不活挂了,为啥呢?为是因为。嗯。
他们公司就这些公司招过去招,尤其招的硕士,他招的过去实际上你要能动手的,你动手能力比啥都强。如果你代码对学校好的话,人家肯定不会要你的。不像如果你是博士的话,可能不会特别注重这方面。
他可能会去靠考你一些核心的能力或者对网络的一些理解了什么的这些东西吧。我觉得但硕士的话,肯定要的是动手能力。如果你。作成能力不强的话,我觉得肯定就比如说oppo。
如果说我对那些常用的网络没有那了解他们的使间,但是我的那个代码能力很强,把那些代码都能写好。我觉得我我跑很就过了。就这样的原因。所以说我其实我我因为总结下来之后。
我也是这段时间其实虽然已经拿到offer,但是我还是在学一些就是东写然后在整天在闲了就在列个上刷刷题题写代码,我觉得这是比较重要的,就是一个核心能力嘛。然后内中心这个其实呃我最后去中心的话。
也是因为是还是在西安嘛,这样一个原因,我最后留在留留在中心,但是呃。他面试的话其实也是我想一下,面了三面。对呃,第一面也是讲项目。但是那个面试官,其实他对我的了工作的东西不是特别了解。
但是他有问了我些问题,就从放假的时候问了我一些问题。然后最后也是他问我一个我问了我一个堆排序的问题。那我写简单写写了一下思路,就是把用伪代码简单写了一下。
就是说你看就所有的公司即我定在就这三家到现在为止,所有的公司都考察你的数据结构和代码代码的一些东西了。所以说如果你以后想找算法的工作,这的有数据结构以及代码呢,你一定一定要不管用点啥语言。
你的话用pythonjava这些这加啊都行。但是我我建议啊是最好用python简单一点写数据结构的题的话,就代码写代码。因为面试过程中。其一下太太繁琐了。对。会有这种这样的问题。然后的话。
然后二面其实也没有问啥,二面就是简单的聊了聊。然后他主要是觉得我的简历上的写的还不错,然后有一些文章,有一些专利这些的东西。然后所以上面也聊的比较顺一点,最后直接谈了薪资嘛,然后这就算那啥了。
然后第三个,第四就是中国移动这块,中国移动我最后没有选择中国移动学,就是因为太太晚了,你知道吗?呃,晚到什么程度,他到10月10月底11月份这样这样的一个原因,就是可能没办法去等这样。
所以最后也是因为他当时跟我说的中国移动就是可能在上海,我考虑了几下,不太不不是特别想去。所以最后就没有没有没有选择去是这样的一个原因。嗯,然后的话就是其实在面试的过程中,真的你会踩很多很多的坑。
比如说我之前嗯。在那个做苏宁和那个。顺分就妮和顺丰的笔试的题的时候,他们俩是都是7点。一个是7点哦,一个是7点,就是7点半。但是我我居然没有发现顺丰的那个时间是可以往往后顺延半个小时的。
我没有注意这个我在7点7点半的时候把那个打开了,但是我边在做呃那个苏宁的题,要边在看顺丰的题,导致我的时间浪费了很多。最后苏宁的题我做完了,顺丰的题我跟你没有做完。
所以说大家在嗯那个笔试过程中也要注意这些问题。如果说两两两家公司的话,他们是嗯他们的时间是重叠到一起的,或者是。有一点重叠的,你要考虑一下,看一下是不是可以就是简单往后搓一搓这样的一个情况。
就争取让自己嗯。就可以参加更更更多的笔试吧。我觉得就是你参加的笔试更多,你的面试的机会更多嘛。就是说如果说你的简历没有优秀到,说直接可以去直通面试这样的情况。
比如说笔试是你能不能参加面试的一个很关键的情况嘛?而且大多数大多数公司的笔试都比较难一点,你要好好准备一下,花比较多的时间去准备这些东西。然后还有的话就是7月这边。
我当时跟这边做了一个那个一个耍机班还是什么?就是这么讲数据结构的嘛?哦我真的以前是对数据结构啥都不知道,你知道?我就知道有个呃数组堆栈这些。就是呃呃队列和战,我就知道这四个好像,其的我都一个也不知道。
你知道吗?什么R叉数了,然后我真的是一点一点都不知道。我转过来的时候,就把那些东西学完之后,我就发现我我我当时啊就是那个积极学习升理学习算法,学完之后,自己做一些小项目之后,我觉得哇我觉得好自信。
我觉得我牛逼到不行了啊怎么样怎么样的。哇,但是就是你当你面试一两次之后,你遇到点错折,你就发现自己真的是差到哪里了,就是说这样的。然后我就就从那块又静下静下心来就去好好补出据结构和代码方面的东西。
这个需要过程。对,所以说大家不能急,我觉得。不管你秋装找的好也罢不好也罢,嗯,都是一个过程。只要你不断去学习,不断去提高自己就行了。我觉得有的时候三翁0马也不一定不是什么好事,对吧?就是三翁0马燕知飞。
焉知飞虎福嘛,对吧?就这样一道理,就是说也不是因为我自己一直都是这么想的。对对对,是那个课是那课。然后的话我还我还可以给大家推荐一些一些课程是我在网上看到的。我自己的一本教。
一个叫就是他B案上直接有免费的课,叫陈小玉的算法与数据结构这门课。我强烈推荐大家推荐大大家去看一下。就陈小玉的就是去学算法那个作者。很厉害很厉害很厉害。被道。然后你在配套上7月这个就是那个那个题。
面试求职的第第四题,以及他们的那个刷题班那个简单的做一做做做完题,然后多刷一刷那个课堂上的题。我觉得数据结构这块就没啥问题。因为大多数公司他不会考特别特别难的。
你什么呃我我我建议这个就是二叉树的呃二层二层便利。然后就是嗯还有就是列表的翻转,还要然进去写快速排序或规律排序。就盘脆多多了就基本基本就这些了。大多数公司都是这样的。对,其他公司的话,有一些大公司。
比如阿里腾讯这些,那就比较难了。就是说我觉得非科班如果你想转这个的话,可能短期之内难度比较大一点。但是你可以去先去一个重等的公司先去积累积累一下嘛,然后学点东西,然后再以后想办法再跳过出来。
也是一种过程嘛。我觉得这是这是一个很好,就不管你秋招找的好不好,首先不要不要气,就不要气馁。因为我我自己也看7月这边经常会有一些找了,就已经工作两三年的,然后自己再转到算法这边的。就通过7月这边上课。
或者说自己其他的一方法,我觉得都是挺好的。就因为人这辈子有很多东西嘛,你不敢说你现在就成功了,现在就失败了什么样的。对吧就是这样的,反正就是数据结构真的很重要,真的很重要。
因为基本上所有都差不多公司面试。最后都会上一写至少一道代码题的。因为要要看一下你的工程能力怎么样。呃,接下来就一些提建议吧。呃我这个我觉得报班这个是不应该说是我在打广广告吧。我觉得应该是这样的一个过程。
就是你去想一下,呃,我报班的话,我可能花50个小时,或100个小时,我能达到我200个小时的过程呃,效果。那我剩下的10个小时,我自己去赚钱,我能赚多少,我会不会比这个学费赚的更多呢?
我觉得是这样一个过程,大家可以这样去想一想。我因为我我当时选择报班,呃,报那个其实这边也是这样想的,其实我也是一个穷学生,穷学生吧,也没多少钱。但是我这样想的话,我觉得我现在投资我自己,我可定多花点钱。
我后面可能能赚的更多一点。就是这样。接下来就是第二点,就是觉得。一定要静下心心去学,你不能说你报班了就。别啥的,如果你不好学,相当于浪费钱没有意义,明白了吧?
还有就是要总结我我每一段时间一两周学就学过的课程算法,这些我都会自己掌过反复的再看一看。是代码看卡,是吧算法的。推导过程的离解过程都看再看一看,就别让你自己学过希望了。因为人这个东西确实会被遗忘嘛。
尤其在就是正八经要,准时开始准备开始招聘之前,一定要系统的再过一遍,再去找再去那啥,还有自己项目上的简历,项项目上的东西,涉及到项目上一些的算法,什么,一定要特别特别清楚。不然人家就觉得你那是假的。
有天糊弄人的,明白了吧?我觉得特特别特别重要。还有就是要转呃要转的话,要转CV这块面的话,是你网就是就从最开始的呃googlenet来net还有呃这些往往现在net其实可以不了解XXnet这些的话会一定要有一定的了解。
这他大概是一个什么样的,但就就每个每每一术的关键关键的就是关键的点就是成功的原因是什么?就简单了解一下。因为这个是对你如果说你做任何工作,你后面去呃设计神经网络什么的,你可定会有一一定的一定的参考嘛。
我是这样觉得的。然后接下来就是刷题,算法题真的真的非常重要。啊,还有就是你找工作的话,见职反正么书真的也很好。不是但那他是好像是针对C,因为我买的是针对C加加的。还有li扣的这边一定要去刷刷题。
刷题真的非常非常重要。就如果你不刷题的话。因为很多题你见过一遍一遍之后,你自己写遍之后你就会写了,它其实不难。就比如说我之前的那个,我当时自己没有自细的写过那个就是。环心列表里面插入一个值嘛,太简单了。
我现在现在去想嗯不就是一个我去两个值,然后去每次比较大小嘛,然后去和他们比较大小,只要只要找到一个比例一个小比一个大的插入中间不就完了嘛。但是有可能有一些就是呃一些临界点啊什么要要去考虑。
但但是他思路就是很简单啊。如果你没见过的话,我提你的思问就。没有那个思路,知道吗?你就嗯写不出来那样的题。其实他们大多数公司真的算法来题不会特别难。大一定要去就是我觉得准备一下,好吧。然后的话就是。
我觉得心态也很重要的,确实过程中。有时候你会特别特别的服,你觉得自己特特别厉害,拿到这个offer了,但有时候你会连连连续被聚集下之后,你就会很沮丧。就觉得有有点怀疑自己觉得自己这里不行,那里不行啊。
觉这我觉得这符个人的一个心态。但是。还是要一定要去。调整好自己的心态,自信一点。因为你的心态好不好?决定了你后面的应对的,就是找在面试,后面的面试能不能好好的发味。如果你发挥后面的面试发挥不好了。
那肯定就就又没有机会了,就不要因为之前的些就是被剧什么的影响到后面的一些结果。我是这样觉得的。然后的话就大概今天要和大家分享的基本上也就这些。就是有问题的话,再给简单再提一下。
看我会尽我最大的努力就是说我了解的和大家去简单沟通一下。也可以啊,没没没必要。如果你python很厉害的话,你也可以没必要说是呃因为如果你做CV这方面的话,其实python也可以了。
我觉得因为我有一个同学他就只会python,他找到了NLP的,找NLP的部门也找到了。是在oppo。对。因为你临时去学一个,但是其实怎么说呢?你如果你说你pasthon很厉害的话。
其实让你去转C加加也还OK吧,我觉得。不会特别难,因为比就是比从小白简单一点。但是其实如果你现在找工作的话,我觉得如果是销招的话,也够了。python够了。我是我是CR的多一点。没有吧。
我没有见过明我我至少没有没有明确要求说是这些加法。因为我我有同学就只会python,找到了找到了一定的NLP的工作。对。但是会见CD加更好了,肯定是这样的。就7月那个7月那个呃求职第四第四第四题。
不好意思啊,7月那个面试求职第四期嘛,然后还有一个他们配到那个刷题班,还有一个是那个呃陈小玉。陈小玉那个拒学算法里面,他在B站上有一个呃数据结构与算法,叫陈小玉。这个讲老师讲的也很好。呃。
对其实不应该说是机器学就会分分成个小的判,可是人工智能就不能会分很多小的方向。呃,机学习现在已经。呃,逐渐的慢慢很多大厂就已经用的用的很少了。然后的话深度学习这方面的话会有CVNLP还有推荐系统之类的。
呃,总的来说的话,现在是CV更难找一点。对。然后NLP和NLP和推荐系统相对好找一点。因为CV现在你看嘛,现在CV落地的产品比较多嘛,比如说灵通和一些矿石这些的人脸识别这些。是这样的对。
所以说相相比来相比较之一下,CV可能更难找一点。是也不是说门槛高,是因为找的人太多了。所以说门槛自然也就高了,人太多了,人家肯定要在里面挑了。嗯NLP和推荐系拟化相对更少一点。因为你想吧。
CV和NLP在很多高校的实验室还还是会有人在做的,会有老师老师会有行友在做的。我至少我都现在没有听过说哪个高校的老师在做推荐系统。你再想想是不是这道理。还还还有啥问题吗?就是我我刚说那那几门课。
我觉得大家真的可以去看一下,一个就是。NLP怎么准备?嗯。对,CV的岗位很多,这是真的,但是他的难度他的人也多。是这样的,我者但相比来说就是CV真的是比嗯那个啥嗯。哎。
但是我觉得不一定未来N该LP的发展,说不定会慢慢起来。这个是。我觉得是嗯有可能的。P怎么准备?呃,这个我还真不知道。要不你和区域这边聊聊那啥,因为我对NLP了解比较少一点。还有问题吗?对我是在西安。
所以我说你应该知道我是你学校的了。我也是搬道出家吧,应该是这样的,就是说自己。呃,杨儿杨2下学期的时候。才决定的才决定想转的。因为自己本身在实验室的话,是软硬件都会一点点,但是都又都不是特别精通。
我面的。我面子应该有10,我想想。
人工智能—面试求职公开课(七月在线出品) - P2:O(N)时间解决的面试题(中) - 七月在线-julyedu - BV1Xf4y1r74s
🎼,欢迎收看契业算法公开课。我们这堂课的内容继续讲ON时间内解决的面试题。我将从如下几个方面讲述本课,现在谈一下ON也是本次课的一个总体。然后讲7个例题,最后总结结束本课。那想谈一下总体。
就是主要今天讲组合数学上的下一个排列,上一个排列,还要通过证明巧妙的证明解决一些实际的问题,也是ON的。然后树立一个理念,就是枚举和计数是不一样的。我们为了计数不一定要枚举一组一组解。
如果只算一个数的话,可能比枚举的复杂度要低。因为枚举有多少组解,你都要一个一个枚举出来,而计数可以一次数很多个,我会讲一个动态规划问题,这个问题有点难,就是最大子数组合的一个变种。看具体的题。
第一个题是lead code上第31题。也就是下一个排列,C加加STR里面也是这么实现的,也就是找到字典序里面刚好比它大了。下一个排列。比方说12345,下一个就是12354。那么最后一个排列。
54321的下一个认为是12345,这个题目比较简单,大家也比较熟悉。我主要讲一下这个算法是怎么回事,可能有人已经知道这个算法了,因为可能也背下来过,大概讲一下。😊,假设原排列是这个A0到AN减1。
我们希望找到下一个排列,就是B0到BN减1,它的前M位和A是相等的,一直到BM减1。那BM比AM大,因为B的字典序要大嘛。另外呢?B的后面一定是按照升序或者叫不减序排好的,为什么呢?
因为B的字典序在这个时候已经比A大了。我们希望B的字点序是比A大,并且最小的,那么后面显然是按照升序排好了,B的字典序才最小。因为后面的顺序已经不影响B和A的大小关系了。另外一点是希望M尽可能大。
也就是相等的位置尽可能多。😊,我指的相等位置是指前缀。因为只有这样,B的子典序才尽可能的小B和A每多一位相等,B的子典序就要小一点,因为让这个大一点的这个出现的尽可能的晚。下面是一个形象一点的表示。
目前的排列是这个样子,括号里面可能不止一个数AAXB。那么下一个排列呢就是AAYB撇。那A和A是相同的。那么这里面AY显然是大于AX的。我们希望A尽可能的长,这就是我刚才说的道理。
因为我们希望这个下一个排列的字典序尽可能小。A越长,下一个排列的尽可呃字典序就越越小。那么AY是大于AX的,因为它的字典序还要比它大嘛,这是第一位。这个能比出大小的大于。那么B撇呢它几乎就是B里面的数。
为什么呢?因为原来AX。这个在B外面,那么现在AX在B撇里面,那原来AY显然是在B里面呢。那么现在AY不在B撇里面,所以B撇和B从数的种类上来讲,其实就差了AXAY这么一个数,所以它几乎就是B里面的数。
但是B撇是按照生序排好序的。原原因,我刚才也讲到了,只有排好序,这个排列的子点序才尽可能小,所以有两点一点是这个A尽可能长,一点是这个B撇几乎是B里面的数,并且是排好序的。
那么这个AAY大于AX是显然的。因为要字点序下一个大一点。那么关键问题就是如何确定AX,并且我们要知道AX和AY这个和哪个数换是最好的。😊,那么确定AX我们的理念就是。这个AX的右边一定要有数比它大。
才行。才是一个候选的X,因为我们左边是不可能被换的,左边是一样的嘛。所以我们找到一个AI1个X。如果它的右边有数比它大,这X就是个候选的那让A尽可能尝是什么意思?也就是X。
我们希望是最右边一个满足这种条件的数,这就是我这里面写的,我们希望AX右边的数,每个数的右边都没有比它大的。因为AX是最后一个满足这种条件的数。那么言外之意就是AX右边的数其实是按照降序排列的。
也就是B其实是按照降序排列的,为什么呢?因为AX加一的右边。没有一个数比AX加一大,也就是AX加一比右边所有数都大。所以AX加一是大于等于AX加2的。同理AX加2是大于等于AX加3的。
所以这个X右边也就是B这个序列其实是一个降序的序列,也就是不生序的序列,因为后面有可能是相等的,所以这个。AX加一大于等于AX加2大于等于一直大于等于AN减1。所以这个AX。是小于AX加一的。
这个是我们想找到的位置。那我们看一下算法,算法简介为二找一交换一翻转,找到两个位置,交换一次翻转一下,我们看一下。我们找到最后一个严格升序的序列的首位,也就是什么叫严格生序呢?
就是AI小于AI加一的这么一个位置。那我们定义为X这里面最后一个是指从左往右找。我如果从右往左找的话,就找到第一个。我们把这个位置定义为X,所以AX是小于这个AIX加一的。那么刚才这个。
AAXB定义为A就是0到X减1。B呢就是后面X加一到N减1这X我们已经找到了。那我们看一下AX要和AY换AY一定是大于AX,且AY最小。因为我们希望。A尽可能长已经满足了。我们希望AY比AX大。
并且最小。原因是希望这个下一个排列的字点序尽可能小,只要大于AX就行了,我没有必要要那么大的,所以是大于AX里面最小的。首先Y一定存在,因为X加一就可以作为一个Y,因为AX小于AX加一嘛。
所以Y一定是存在的。并且刚才已经说了,AX后面的数都是降序的。😊,所以我们从后往前找到第一个大于AX的位置,其实就是Y了。因为这个后面的数是一个比一个小的,那么倒着找的话就是一个比一个大。
那么我们找到第一个就是刚好大于。AX的最小的那么一个数,我们就找到这么一个位置。Y了。当然因为它是有单调性的,其实我们可以用二分查整,但是这里面二分不二分不影响总体的复杂度。
因为前面找X已经用了ON的时间了,这里面即使降为logN总时间还是ON。那么交换我们找到了这样的X和这样的Y,我们把这两个数交换,注意交换之后。新的AX加1到AN减1,就是后面那些数仍然是降序的。
因为之前是降序的,我们找到第一个大于AX的位置。AY我们把它换小了,所以它总体上还是一个降序的。那么我们刚才说要对后面那些数进行排序,对一个纯降序的数做排序,没有必要跟翻转是一样的。
我们把它翻一下就变成正序了。所以后面做一个逆转,也就是翻转。所以这就是我说的,找到两个位置,二找一交换一翻转。看一下代码,代码也很明显的,两个for就是二找这一个交换这一个翻转。关键看一下。
如果X小于0,也就是我们找不到这样的位置,那就是刚才那个例子54321,它没有一个升序存在,全都是降序54321嘛。所以。把它还原成第一个排列,也就是直接做一个反转,这是特殊情况的特殊处理。
否则我们找到了一个X,并且找到了一个这样的Y。然后做一下交换,对X加一做一下翻转,就把后面排好序了,就找到了我们要的下一个排列。那其实还有一个算法是上一个排列,其实是一样的。刚才说找升序,这是找降序。
刚才说找AY大于AX,这里面是找AY小于AX,且AY最大也是二找一交换一翻转,把这个代码稍微改一下,其实改两个大小大小于符号就可以实现上一个排列了。那这个优点其实就是两点,第一是复杂度是ON的。
第二是即使原始的排列里面的数有重复,它也可以正确应对。所以这个是我想讲这个算法的一个原因,帮助大家理解字典序,理解这个ON时间的找上下排列的算法。那么看第二个问题。给定一个零一串。
这个零一串呢长度为4N,包含2N个02N个1,恰好一半0一半一。当然顺序不一定。你可以把它切成若干段,切完之后再拼接,要求拼接出的两部分,每部分恰好包含。这个N个0N个1,也就是每一部分恰好。
一半的零一半的一,并且使切的段数最小。首先我想说一定可以切出来,因为我大不了切成一位一位的。就是每一个里面长度都是一,然后再拼的话就选N个零拼到一起,N个一拼到一起就可以了。所以肯定是能切出来的。
但问题是怎么切的刀数最少,或者说切的段数最少。因为最终的段数其实就是这个刀数加一嘛,所以刀数最小和段数最小是一样的。举个例子,比方说0101其实切一刀就可以。从中间劈开就是两个01。
每一个里面都有1个01个1嘛。😊,那这个例子呢这个要切成三段,也就切两道,把第一位拿出来。😊,然后0中间呢是01。然后最后一位,那么这样的话,中间这个作为一部分,这个零这个一也作为一部分。
所以每一部分都有一个01个1。那其实答案无外乎就是二和3,我们可以证明一下。首先我们认为下标从零开始。那么原来那个串我们定一个函数叫做FXFX定义在0到2N之间,再大的X是没有定义的。定义的是什么呢?
是这么一个窗口里面零的个数与一的个数的差,窗口的大小是2N。这个不是正好从X到X加2N减1,所以这个只能定义到2N。因为那个串长度一共是4N嘛,所以我这个X是只定义了。这么多。
那么首先我们有对于这个函数来讲。F0加F2N等于0,什么意思呢?F0是0到2N减1F2N呢是2N到4N减1,这两个一加其实是整个串了,整个串里面零的个数与一的个数差是0。
因为整个串恰好2N个02N个1嘛。那么如果这两个数都是0,因为它们和是零嘛,如果这两个数都是0,那么相当于从中间切一刀切成两段就可以完成。因为左半部分恰好也是N个0N个1,右半部分也是N个0N个1。
其实就是对应于第一个例子这种情况。那么。关键是如果这两个东西不是零,那么显然一个小于0,一个大于0。这个没关系,哪个小于零,哪个大于零没有关系。那我们分析一下它的它是奇数还是偶数,它始终是偶数。
这个为什么呢?因为他们。总和零和一的总和这个窗口的大小是2N嘛,窗口大小是2N,所以零和一的总和肯定是个偶数,那零和一的差也是偶数,因为和和差在这个奇偶性上来讲是一样的,所以。这个FN始终是偶数。
并且假设我们认为最开始是负的,但是最开始挣的也没有关系。如果从负数跳到正数的时候,我们怎么跳呢?从FX变到FX加一的时候,会有怎样的变化呢?一种就是这两个窗口是一样的,也就是我们失去一个零。
又补回一个零或者失去一个一补回一个一。那么这个FX是不变的。另外一种呢就是我们失去一个一补进一个0,那么这个时候FX其实是增加二的,因为FX是零的个数减一的个数。那还有一种就是失去了一个。😊,0。
补了一个一,那么。这个同理是减少二的,因为零的个数减一的个数是减少二的,所以FX始终是偶数,并且每次增减都是2。那么从负数跳到正数的时候,这个就相当于一个连续函数,肯定会经过一个FX等于零的点。
那就是我想说的这个意思。😊,它始终是偶数,并且由负数到正数,或者说由负数正数到负数,这没有关系,必然出现这么一个位置,FY等于0Y在这个中间。注意Y肯定不是零,也不是2N。
因为我们前面假设这两个位置都不是。所以Y是中间的一个部分。那我们看这个Y是怎么样的一个定义呢?Y其实就是FY其实就是Y到2N加Y减1这么一段里面,零的个数和一的个数差,它等于0,这一共2N个数嘛。
它等于零,就说明这一段里面一定包含了N个0N个1。所以我们找到了一个这样的Y就找到了这么一段。那么我们把它切成三份,一部分是0到Y减1一部分是。😊,2N加Y到4N减1。
也就是这个之前的那一段和这一段之后的那一段这两段。的和显然也包含了N个0N个1,这一段本身包含了N个0N个1,所以这两段可以拼成一段,这一段单独作为一部分。也就是我们切了两刀,做了三段。
所以答案无外乎就是二或者3。因为我们没有必要求出这个Y来。我们只需要知道答案是几就可以了。所以答案是二或者三怎么规定呢?我们看第一个窗口就可以了。刚才已经说了,如果F0是0,那么FRN一定也是0。
那么从中间劈开就行了。所以答案就是二,也就是切成两段。啊,否则的话,如果F0不是零的话,我们一定要找到这么一个Y。当然这个Y不用找,一定能找到切三段就可以了,把中间这个作为一段,前面一段,后面一段。
那么其实答案无外乎就是二和3,我们就是统计了一下这个零和一的差,也就是第一个窗口,所以这是一个很简单的算法,也就是这个样子,这个没有写真正的代码写了一个伪代码。😊,刚才说FX的定义。
我们其实就是算一下F0还循环0的2N减1。如果是零的话,就加一下,是一的话,就减一下。最后呢D就是我们想要的F0。如果D是零的话,答案就是2。刚才已经说了,从中间切开,否则答案就是三。
我们需要找到一个位置外,然后那个位置长度为2N的窗口,恰好包含了N个0N个1。然后左右分别作为这个另外一部分,所以这个是相当于切成了三段。😊,所以我们代码就这么简单,代码并不需要我们找到那个Y值。
当然要找到并也不难。大家可以继续的想一下。我们看另外一个问题,这个问题是改编自一个only assignment,一个公司的网上的题目。它给定一个长度为N的数组,A告诉你A里面只包含了正整数。
我们把下标从零开始,再给定一个元素X,我们求一个位置,MM是大于等于零,小于等于N的那0到M减一中X的个数。当然如果M等于00到M减1是个空数组,这个X的个数和后面也就是M到N减一中非X的个数。
如果M等于等于N的话,也就是这个东西也是个空数组。我们要求相当于找到一个位置,这个位置之前等于X的元素个数和这个位置之后不等于X的元素个数相等。首先我们都不知道这个这种位置一定存在。另外。
如果存在有几个呢,我们可以看一下,其实简单的分析一下就可以看出来。假设这个所数组中一共有小写X这么多个大写X。那假设我们已经知道M是多少了,那么我们并且假设。A0到M减1。
也就是前半部分前M个元素有Y个X。那么后面呢。后面M到N减1,后面不是X的个数是多少呢?我们可以用N。减一下M。再减去X减Y什么意思呢?这个后面的元素个数是N减M,因为前面有M个嘛,那后面的X个数。😊。
显然是X减Y,因为总体有X个,前面有Y个,这是X个数,这个是后面的元素个数。所以一减就是后面不是X的元素个数。那这个把这个括号去掉,就是这这个东西N减M减X加Y,这是后面不是X的元素个数。
我们要求后面不是M呃X的元素个数和前面是X的元素个数相等,也就是N减M减X加Y等于等于Y。😊,这个。因为前面有Y个X嘛,这个后面这是非X的个数,那这两个相等其实消掉之后发现最后解出来M就是N减X。
所以这个M是不仅是存在的,并且是唯一的。它求M其实就是求一下这个。总体上有多少个X就可以,就是求这个小写X。所以这个算法非常简单,就是循环一遍,数一下有多少个大写X,然后返回这个N减X就可以了。
所以一个看似很复杂的问题,经过分析,实际上就是循环一遍,数多少个这个大写X就可以了。😊,那么显然它是1个ON时间和O一空间的算法。当然用前缀和什么什么都可以实现。但是我这么分析是不需要前缀核的。
直接统计一下有多少个大写X就可以。有有这个X个的话,答案就是N减X。😊,那有一个思考题,其实就是说有10个硬币,这10个硬币里面呢,我们随便说一个数,比方说有4个是正面的,正面朝上的。
剩下6个呢都是反面朝上的那你不允许你开灯。言外之意,就是你不知道哪些是正面朝上,哪些是反面朝上。当然你可以把一些硬币反面。但是你反面呢,你也不知道它是正面朝上还是反面朝上,让你把它分成两组。
希望两组正面个数相等,其实和这个是一个问题,提示一下,我们把前六个作为一组,后四个作为一组,把后四个翻一下,也就是那个后四个硬币全都翻一下面。那么这6个里面和这四个里面正面朝上的个数应该是相等的。
证明其实和刚才讲的是一样的。😊,我们继续看,这是我给pat出的一个题。pat是目前很火的一个认证,叫programming ability test。我出了一个什么题呢?就是说给定一个字符串。
只包含PAAT,因为正好和pat是是同样的。那么当然不不不是说只包含1个PAAT,就只包含这三种字符,求一共出现了多少个pat作为子序列。子序列的意思就是可以呃这个不挨着,就是比方说第一P。
然后APPA那么第一个P和第4个A也可以构成1个PA,那总共构成多少个pad呢?这个题很简单,我只是想说计数和枚举不同。如果我们要枚举,肯定要把所有的PAAT都枚举出来,写一个三重循环。
然后看一下形成多少个pe。那么这个显然是个三次方复杂度。那如果我只计数的话,ON就可以做什么意思呢?我们记录。PAPA和PAAT分别表示。这个第I位之前出现的P的个数。
出现PA的个数以及出现的pe的个数。那么我们直接计数就好了。如果当前是个P的话,那么显然P加一下。那如果当前是个A的话,注意这个这个A和之前的所有的P都可以形成一个PA。
所以PA的总个数加上一个P就好了。那跟刚才道理一样。如果是T的话,这个T之前所有形成的PA和这个T都可以形成一个pa,所以pa加上它之前的PA就好了。所以就是一个循环,加上3个异。😊,啊。
当然可以写两个意服。如果因为只有PAAT3种字符,这个最后那个不用判断,不是这两个一定是T了,这个都是常数优化,这都没有关系。那这个时间复杂度是ON,空间复杂度是O一。因为我连数组都没有用。
只用到了这种三个变量来实现。那给大家一个思考题,就是 code上115题,其实跟这个差不多,只不过它让数的不是pe,而是另外一个字符串出现的次数,做法是一样的。但是空间就不是这个O一了。
时间也不是ON了。因为我这个其实是3N的复杂度。那个时间应该是M乘以NM是要找的这个字符串的长度。所以那个M等于三的一个特殊情况,其实就是这个问题。😊,那么继续讲我们这个题,这个题也比较有意思。
这是codlity上的一个题,就是给定一个数组。求。一个至少包含两个元素的子数组,满足这个子数组的平均值尽可能小。当然输出有一定要求,我输出的是这个数组的起点,当然有多个的时候输出最小的。
这样就保证输出是唯一的。先讲一下为什么要求这个子数组至少包含两个元素,如果对子数组长度没有要求的话,显然我返回一个最小值就可以了。因为这个。平均值最小嘛?我只返回一个最小值的话,平均值肯定是最小的。
因为再加一个元素就会把这个平均值抬高,因为返回率是最小的。所以它要求我们返回这个子数组,至少要包含两个元素,这个是这个题目的一个意图吧。😊,那么我们假想一下最优解。如果最由解的长度是偶数的话。
我们就把它拆成。长度为二的若干段就是相邻的两个元素作为一段。如果最有解的长度是奇数的话,我们就把它拆成也是长度为二的若干段儿。但是最后一段长度为3,当然也可以拆成第一段长度是3,后面若干个长度是2。
我这样拆是什么意义呢?😊,自由解中我们拆成的这些段,每一段平均值必须相等。我们考虑一下为什么。如果有一段平均值比自由解小。那么自由解里面其他段肯定有一段自由解比平比这个自由解要大,为什么呢?
因为有一段小的肯定有一段大的把平均值拉回去,那么这个比自由解。平均值还大的那一段,显然是和整个那一段是自由解来矛盾的。所以这若干段里面所有的平均值都相等,不然的话就有大有小,有小的就有大的。
有大的话就和自由解矛盾。那这个意思就是说,我们只需要看这个子数组长度为二和为3的就可以了。并不是说更长的得不到最由解,而是说自由解包含了要么长度为二的,要么长度为三的,更长的可能也是最优解。
只不过那个平均值是相同的。所以我们要找平均值最小的,只要看长度为二的段和长度为三的段就可以了。那至于怎么看,其实看法很多,因为二和三是常数,就跟上面那个pe是一样的,我们可以直接直接循环看一下。
也可以用前缀和减一下,也可以用滑动窗口来看一下,怎么看都可以。😊,这就是我刚才说的,只需要考虑长度和为二和V3的段,因为其他段自由解绝对不比二和三的自由解优。那另外一个是说,我们可以用乘法代替除法。
避免一些精度问题。当是前提是不易出。呃,我这里面采取的是滑动窗口的方法。toal2就表示目前长度为二的段的总和。因为我没有除以2toal3呢,就是长度为三的段少总和。当然我可以在循环的时候直接算。
我之所以把这些提前算出来,就是想让它继续滑动,对二的话,加上一项减去一项,对于三的话,也加上一项减上减去一项,最后呢求出来bi塔2和bi斯三分别是两项的最大值和三项的最大值呃。
最小值是两项最小值和三项最小值。那么这个就是我说的用乘法代替除法,这个其实应该算bi塔2除以2和bi斯三除以3嘛,但是我把它乘一下减一下,如果等于零就说明这个二的平均值和三项的平均值是相等的。
那么就返回这个较小的。因为答案要求返回起点较小的嘛。如果小于零哪个小返回哪个。😊,这个就是题目也非常简单,它只有一个循环,所以它的算法是ON的。😊,这个巧妙之处在于。
我们把这个等于二和等于三的单独拎出来,并且证明了最优解一定可以包含。就是有一个等于二的或者一个等于三的,一定可以得到最优解,就避免了我们枚举所有的子序列了。那么我们看一个这个环形最大子数组合。
这个问题呢是ITin5,这是另外一个网站。ITin5是一个域名,它上面的第九题,那么给定一个数组,它是环形的,也就是最后一个元素和第一个元素是相接的。我们求这个最大子数组合。跟普通最大子数组合有点差异。
它那个最后一个元素可以接到第一个元素上面去,就是从一个环上找出一段来。那么普通最大子数组合是什么样的?比方说这个例子12-456-9,那么显然56是最大的,这是一个普通最大子数组合,那么。
还有一种情况是开头和结尾的一部分。也就是我想说明的一个情况,就是环形子数组环形的最大子数组合无外乎两种情况,一种就是普通的最大子数组合,一种就是开头的一段和结尾的一段的和,这种普通的是解决不了的。
比方说这种情况,中间三个都是负数,那么显然129是最大的,这个用普通的是解决不了的。那么我们看一下无外乎就是普通的求一次,那么这种情况怎么对对待呢?它不就是总和减去中间的一段嘛。那减去中间的一段。
实际上就是求中间这段的和最小就可以了。所以。😊,这种环形的比普通的最大子数组合复杂不了多少,无外乎就是普通的求两次。就是我说的先求普通的最大子数组合应对这种情况。另外可以考虑用总和减去最小子数组合。
应对这种情况。因为这个头一段尾一段相当于中间求一个最小的子数组合,至于怎么求最少。显然可以这个直接用那个算法求,当然也可以把原始数数组,每个数取相反数再调一遍,然后用总和减一下就可以了。
这个是偷懒的方法,当然也可以写两遍,求一次最大求一次最小。这个算法也比较简单。根据最大子数组合的算法,它也是一个线性的,只不过调了两遍。所以这个环形的比普通的其实难不了多少。我们看最后一个问题。
这个问题有点难。它也是 codedi体上的一个问题,给定一个数组,这个也是最大子数组合。要求呢你可以交换两个数,当然只允许交换一次。当然你可以不换不换,你可以认为自身跟自身交换。
然后呢还是求最大子数组合。那么我们定义。关键看我怎么定义这两个东西,定义好这两个东西就可以递推就可以动态规划。我们看一下FI是两部分之和,是哪两部分呢?一部分就是以AI结尾的最大子数组合。
这个其实跟我们求普通最大子数组合没有什么区别。当然这部分可以为空,也就是全是负的时候,我可以不要这部分,与注意我是与的关系并不是或,它这两部分一段一个是一段,另外一个是一个单点,或者说单独的一个元素。
也就是FI表示的是以AI结尾的一段最大子数组合,以及。😊,单独的一个位置。也就是0到I里面单独一个位置,这两段的和的最大的那么一个和。当然这两段是没有交集的,也就是同一个数不能取两次。
我这一段如果有的话,这个A0到I里面的就是单独那一个点,不能取在那个段上。也就是我们可以简单的理解为FI是一段加上一个孤虑点的最大子数组,就是最大的和,不能叫子数组了。因为有一个孤虑点。
也就是FI是一段加上一个孤虑点的最大的总和在AI之前的。😊,那么地推式有了这个定义,地推式就有了,它是这个样子。这个我可以稍微解释一下。如果。我们用到FI减1FI减1已经算好了。
我们把那一段加上AI就可以了。因为那个孤虑点在哪儿,我们根本不关心,因为这个。这个加上AI,即使那一段是空的,我加上1个AI也没有关系,就是FI减一里面这一段不是说可以为空嘛,它是空的,我也没关系。
我就认为那一段就是AI了。那么那个单点孤立点还是FI减一那个孤立点,所以它有可能是这种情况。另外一种情况呢就是这个。😊,FI选择跟那个FI减一没关系,我让FI这一段是空的。
那么我就选择这里面的一个孤立点。那么这个孤立点其实就是A0到AI里面最大的就可以了。所以这个FI递推式就是这两种情况取最大。那这个F有什么意义呢?F里面那个孤立点,就是我们想和AI换掉那个点换掉之后。
😊,这个以AI结尾的最大子数组合,我们已经求出来了。那么如果有一段我们把AI换成那个孤虑点,剩下都单独求就可以了。所以FI是这个孤虑点给我们提供了跟AI交换的那个元素,提供了一个备选元素。
那么们看GIGI其实就是。😊,以AI开头的最大指数组合,这个其实跟那个。啊,传统的最大子数组合没有没有区别。那么GI其实就是GI加一,因为我这个I是相当于由大到小循环,或者说是倒着循环的。
所以我定义的是以AI开头的最大子数组合。所以GI就是GI加10取较大的,加上AI这个地方是没什么特别的。关键请大家仔细理解这个FI。😊,那么。我们看一下,如果AI和AJ交换,我们认为这是小于。I的。
并且我们这个最终的和是包含这个AJ的,或者说包含原有的AI。我们把AI和AJ交换了。那么实际上它对应的最大子数组和对应于这个东西。这个就是我刚才说的DI是。
包含了AI以及这个AI更右边的那些元素FI减1其实这个时候是没包含AI的,所以GI减去AI也是把AI去掉了。FI减一里面包含了一个单点,虽然那个段可能是空的,那个单点就是和AI交换的那那个元素。
也就是AJ。😊,那实际上我是要求这个东西最大值。这个东西最大值言外之意就是交换的那个点在FI减一里面。那么这个是交换的时候,如果不交换呢,就是maxGI,这个就是普通的最大自数组合。
当然这些情况只是实现了交换那个元素,小于I的时候,那么对于大于I的话,我们把数组反过来再做一次就可以了。😊,大概看一下代码。先做一次helphelp就是我刚才说的定义FIFI就是这么定义的。
那么定义GI。然后取这个式子的max,关键是这个GI减AI加FI减1。大家仔细理解这个GI减AI就是把AI扔掉了,换掉AI用FI减一里面的那个值换掉了AI。所以这个取最大,然后再把它翻一下。
这个reverse就翻了一下,再调一遍,就求出来最后的最大值了。那么显然这个算法也是ON的,所有的都只循环了一个都只循环了N次。注意还有一个普通的最大字数组合,在这里求了。
因为我在求GI的时候可以顺便更新。因为这个其实这个循环就是普通的最大字数组合。因为这个只不过用了一个GI嘛,GI其实就是原来的那个什么and啊什么那个东西,以I开头的最大字数组合。
所以这个answer在算GI的时候,同时更新了一个普通的最大子数组合。也就是我们考虑了三部分,一部分就是J小于I的交换,一部分就是普通的最大字数组合,还有一部分J大于I了。这个通过翻转做了一遍。
所以这个是最终的一个解,这个题其实是比较难的一个动态规划了,比那个传统的最大子数组合难一点。但是仔细分析,关键是理解这个FI是什么东西,请大家仔细思考,最后做一下总结,还是要多思考,多练习。
另外刚才我说那个理念,就是属。😊,这个问题,计数并不等于枚举。那没有讲到的问题其实还有一些。但是这个不属于ON了。有些问题从这个N3次方可以优化到N方的这个原理其实和这个ON的时间差不太多。
然后有两个序列相关的问题,都是和排序这关系比较相大相近的,一个是呃可以每次选一个数放到开头,还有一个是可以选一个数,放到开头也可以放到结尾,你可以自由决定放到哪,那么至少几次排好序呢?
这种都可以ON时间内解决。我在下一次会总结一下问题,然后讲几个新的问题。还有更多的前缀后缀的利用。😊,好,今天的课就到这里。
谢谢大家,欢迎大家给我提出批评。😊。
人工智能—面试求职公开课(七月在线出品) - P3:O(N)时间解决的面试题(下) - 七月在线-julyedu - BV1Xf4y1r74s
🎼,欢迎收看7月算法公开课。我们这堂课的内容是ON时间内解决的面试题。下。😊,我将从如下两个方面讲述本课,先讲例题汇总。我把之前的讲过以及没讲过的问题,分成了10个类别。每个类别里面有很多题目。
最后解束本课直接看题,第一题是和最大子数组相关的。第一个就是最大子数组和,大家比较熟悉。我在动态规划实战A2里面讲过,也是例 code上第53题,方法不特别细的讲。第一个方法就是求记录最小的前缀和。
因为前缀和的差,其实就是一段连续子数组的和。什么叫前缀和就是从第一项开始连续加的若干项。比方说空就是没有数。
是一个前缀和A一是一个前缀和A1加A2也是A1加A2加A3也是显然我们可以线性时间把前缀和算出来。那么以AI结尾的最大子数组的和,其实就是从A一加到AI再减去前面的一个比较小的前缀和。
比方说A1加到A5减去A1加到A2,其实就等于A3加A4加A5。那么。😊,至于减哪个显然要减最小的。因为我们被减数一定的时候,减数肯定是越小,我们这个和就越大。所以我们就没举前缀最小的那个。
然后当前这一项减一下它就可以了,这是一个线性的第二个方法呢,其实是大家比较熟悉的所谓的动态规划,就是记录你每个位置结束的最大子数组合以AI结束的,要考虑它是不是以AI减一结束的。
然后加上AI或者我AI单独起一个就AI这一个数,这两种情况取最优。那么另外一个问题呢,就是let code上的第52题求乘积。这个和例一很像。😊,那我们也可以类似的考虑。首先如果是面试题的话。
我们需要问一下面试官有没有溢出。因为乘法很容易就得到绝对值很大的数。那我刚才提到了绝对值,因为乘积最大并不一定,前面也最大。因为它两个负数相乘,可以得到正数,所以我们需要考虑为了避免正负数的讨论。
我们需要考虑前面的最小乘积以及最大乘积。所以和和不一样的地方在于这里面我们要记录两个数,而和只记录一个数,但是方法是差不多的。看一下代码,注意乘积没有数,也就是零个数的时候,我默认是一和默认是零。
这个是习惯惯例。不过测试用力应该没有这种这种用例。😊,那现在这个东西是以DI项结尾的最大子数组乘积,这个是最大的,这个是最小的,这个是全局最小的这是全局最大的。注意全局最小的其实没什么用。
我之所以把它列在这儿,是说,如果求最小乘积,我们也可以用这个代码来做。最后return的是最小就可以了。那么对于DI项,我们同样考虑,它自己作为一个可能,要么就和之前的DI减一项的那个来。😊,乘上去。
这是三项曲最小,这是三项曲最大,这是两个式子,就是mini和max的区别。那我这里面用了一个tempo。为什么用tle呢?因为如果我这一项还用mini的话,那么下一行里面也用到mini。
这样就会有些影响。所以这个最好用tampo用tampo的话呢,最后再复过来。当然这max是没有必要用tle的。因为下面再也没有用到的。但是为了这个直观的清晰,我还是用了两个影视变量,那么把它复一下。
然后全局的就是原来的全局的和当前的最小或者最大比较简单。😊,我们看第二个问题,就是所谓的循环移位,循环一位是针对于一个数组或者一个字符串来说的。怎么叫循环一位呢?我把它比方说12345,我移动一位。
就是把一放过来移动两位,就是或者说从这个基础上再移动一位,我就把二放到末尾。每移动一次之前的那些数要往左移动一下,把后面的空位空出来,就像插入排序一样,那么我们目标就是给定一个长度为N的数组。
我们把它循环移动M位问最后结果是什么。显然我们可以一次一次做,每一次都是ON的。因为涉及到所有数都要移一下,那么总复杂度是N乘以M,那这个M特别大,其实是没有意义的。比方说这个我移动5次。
其实还是它本身,因为只有5个数,我转着圈移还是它本身,所以M对N取一数,M再大也没有关系,我们都可以把它化成小于N的一个数。那么。😊,简单的方法或者说一个经典的算法,就是利用。😊,这个翻转的过程。
我们先翻转前MV,再翻转后N减MV再总体翻转。所以我们翻转三次就可以做到。循环移动M尾,无论M等于多少,那怎么翻转呢?就可以这样做翻转。from two是双臂区间,就是一个开头,一个结尾。
不是普通的左B右开区间。如果I小于J,我们就交换,这样相当于从中间有一条对称轴,我们把它左边和右边左边和右边不断的交换,就相当于把这个串翻转了。比方说我们考虑个例子,比方说M等于2。😊。
我们先把前两位翻转就是变成了21345,后三位翻转,就变成了21543,在总体上5个数翻转一下,就变成了34512,就是21543的翻转。
所以翻转三次是很方便的那嗯时间复杂度呢就是第一次其实可以理解为ON。😊,实际上真正细致一点分析是O2N,因为第一次和第二次一共循环了N次,因为这里面一共循环的就是长度那么多次,这M和N减M一共才N次。
最后也是N次,所以是2N。那比方说这个具体怎么写呢?就是先翻转0M减1from和 two是0M减1,再翻转MN减1 from two再翻转0N减1,就是我写了这么一个函数,参数是from to。
我把这个掉三次就可以了。总体是O2N,也就是ON的。😊,那利用到这种翻转的这种方法呢,我在字符串高频面试题里面,例五讲到过一个单词翻转,其实也是利用了这个东西。那还有一个是回文判断,这个比较简单。
其实呢就是把这个变成把这个翻转变成。如果AI和AJ不相等,就return一个 first,这个就相当于从中间对称的那个地方开始,左边和右边相互比较。如果相等,全都相等,它就是回文的,不相等。
就不是回文的。所谓回文就是从左往右读,以及从右往左读,是同一个字符串,这个叫回文,这都是比较简单的,都可以利用类似于翻转的方法来解决。我们再看例3。😊,这个比较重要就是快排的partition过程。
第一个我在排序查找实战例三里面讲到过也是lea code上75题。荷兰国旗问题。为什么叫荷兰国旗呢?因为荷兰国旗只有三种颜色,我们对应于这个 code上那个问题就是对012进行交换上的排序。
因为02就三种的。它原来是把三种颜色的布条排好顺序,所以叫荷兰国旗问题不细讲,那由它引申出来的,稍微简单一点问题就是奇偶数分开正负数分开,注意这个是三种呃,小于等于大于荷兰国旗问题是三种。
那这个呢只有两种就是跟快排的经典partition是一样的。正数负数啊,奇数偶数啊,无论怎么做都是利用这种partition可以ON时间内做到。我在自符串高频面试题。
例一里面也讲到过这个问题叫零1交换排序,其实和这个上面说的这两个是同一个类型。但是呢它求的是最少的交换次数,有兴趣的可以直接去看那节课的内容,还有一个核星号做交换。这个相对于这种就比较简单。因为只。😊。
星号和非型号,我们可以提前数一下星号的个数,但是总体上也是跟partition差不多。ON时间内能解决。还有一个问题,我在数组高频面试题里面例二讲到过,也就是li上第41题,就是给你一个数组。
然后让你看从一开始123看看第一个不在这个数组里面整数是哪一个。我们也可以通过partition或者类似于交换的过程,把AI放到它应该在的位置上去。那么这里面有一大类问题。我也想提一下的。
就是中位数比K大的数或者DK小的数,以及最大的K个数和最大或者最小的K个数的问题。😊,那这是两个问题,其实可以统一解决。比方说DK大数或者DK小数的问题。啊。
首先我们要5个数取第三个数取那个东西作为这个分区元素,这个是递归的过程。啊,包括其中说到三数取中,其实这个算法时间复杂度会退化。算法导论里也有讲过。所以建议是5根数取这个中位数,然后作为分区元素。
然后把提升过程一定要分三段,因为分两段的时候有相同的数,时间复杂度会退化。这里面算法导论,其实它假设了没有相同的数,然后做了分析。我仔细分析过,如果有相同的数分成两段会有问题,还是分三段是比较正常的。
就是把小于等于大于分成三段,然后再继续递归下去,这个是找DK大的数或者DK小的数,那么找最小的K个数其实和这个很像,我们也可以利用partition过程来做。但是做完之后。
首先我要说要分成三段就是小于等于大于。那如果在等于那块可以直接返回。因为我们知道它是多少,那小于大于再继续递归。这个想说的是利用partition找到的这K个数,因为这个要返回K个数是一个数组。
那K个数是没有顺序的。我们只知道这个数都比某一个分区元素小,或者说都比某一个分区元素大。但是这个左边那些数都是没有顺序的,右边一样没有顺序。那如果要有序,我们只能用这种方法再排序。
所以它就是ON加上O logK的。那一个斜起来简单点,但是时间复杂度稍微高一点的方法,其实是用一个堆来做堆里面只维护K个数,用一个最大堆。然后如果超过K个数就把。😊,扔掉,因为根是根是最大的嘛。
所以这个时间复杂度就是N log K,因为堆里面只有K个元素,要循环N次。不过那面试的时候建议写这个,因为这个时间复杂度虽然高一点,但是实现起来会简单很多。😊,那么还有一类就是关于众数的问题。
什么叫众数呢?就是超过一半出现次数,超过一半的数。所以众数最多只有一个,有可能没有。但是要有的话,最多只有一个。这个我在数组那一章里面例五讲到过。那它有一个推广,我之前也提过。
就是找到出现次数大于K分之1的数,众数其实就是K等于2的特殊情况,这种题的一般方法就是用K减一个map或者哈西 table原则上就是如果有K个数互相之间都不相同,我就可以把这K个数都扔了。
不影响这个大于K分之1的数,这跟这个众数分析是一样的。那么这种时间复杂度,注意如果是map有一个log存在。但是如果是哈希的话,时间复杂度是K乘以N的,但是K通常我们认为是常数,所以还是ON的。
因为一般题目都是告诉你要找出现次数,比方说大于3分之14分之15分之16分之1的数,我们就可以用类似于众数的方法,因为K是一个常数。最后时间复杂度是ON的。😊,那还有一类就是单调对战。
这个我在站和队列里面也是例五讲到过注意某一块入站的时候,它的左边界确定什么叫左边界这一块往左能够延伸的最长的长度确定了,出站的时候,这一块往右能够延伸的最长的长度就确定了。那么我们有了左边有了右边。
我们就知道这一块本身它能走的长度是多少。那么它的高度也是已知的长乘以那个高,就是它的面积,那每一块我们都这么做,取个最大就可以了。这个时间复杂度是个ON的,因为每一块只出入站一次。尽管可能有两重循环。
但是时间复杂度还是ON的,所以再次强调算时间复杂度不要简单的直接看循环个数,还是要仔细分析循环变量的变化。😊,那滑动窗口的最值,这个其实我也是在站和队列里面。例六讲到过,它是一个这个呃单调队列的问题。
我们可以用堆来解决,但是用单调队列可以达到线性的复杂度,而且避免了写堆的复杂,它就是一个双端队列。那,这里面再举一个例子,它是口d上的一个问题。我觉得它把单调队列发挥到了极致。什么题呢?😊。
给定一个整数数组和一个K也是整数,问有多少对下标就是多少个peI和J满足这个I到J之间的最大值和I到J之间的最小值的差是小于等于K。😊,那我们可以想一下,如果I和J满足条件,假设我们有I和J满足条件了。
那么它的子窗口就是I加1J啊,I加2J啊,J不变,I不断增加,其实都是满足条件的。为什么呢?因为这个小一点的窗口里面的最大值肯定。😊,小于等于这个大窗口的最大值。最小值呢这个小一点,它候选的数候少。
它的最小值肯定大于等于这个IJ的最小值。所以这个最大值更小了一点,最小值更大了一点。那么这个差距就更小了。如果大窗口差距满足小于等于K,那么小窗口一定也满足小于等于K。
那言外之意就是我们对于一个给定的I来讲,假设我们求出一个尽可能大的J,或者说找到第一个不满足条件的J,因为满足条件都是连续的,找到第一个不满足条件的J,后面肯定也不满足条件了。😊,那么对I加一来讲。
我那个J没有必要再从头再找一遍了。J就从当前的位置继续往右划就行了。所以这里面大家可以看到I和J并没有向左滑的过程,就是这个窗口I到J,然后I加一的时候,J也还要从当前位置不断的加。所以这是一个线性的。
那线性的关键问题是我们如何求I到这里面的最大值最小值,还是刚才那个这个边界不断的在往右走。所以如果我们用一个队列保存这里面的数的话,只要出对的数再也不会入队了。因为窗口在不断的往右滑动。
所以这个是单调队列的一个极致。我们用两个单调队列,一个维护最大值,一个维护最小值。关键问题就是滑动出去的,再也不会进来。我们看一下。😊,这个代码贴的有点小,首先这个就保存最小值,这个保保存最佳最大值。
大家想象一下,我当时讲的那个滑动窗口什么意思呢?我们最小值如果有一个老的值比它大的话,那么老的值显然永远不会最小值。因为有它在这,并且它新滑动窗口无论怎么滑,这个新值在这,并且它小,所以旧值就没用了。
那同理如果。😊,有一个老的值,并且它比较小的话,那最大值就没有意义了。那么这样的话,我们用这个对头就是真正的最大值和最小值。那如果它小于等于K,我们就一直把右边界往右滑,注意I是没变了,这是内存循环。
那如果它不满足条件,我们就退出来,那不满足条件的时候,answer其实加上的就是J减I,就是有这么多对都满足条件,到这是不满足的。那么这个就是我之前讲到的所谓过期,因为对头是最小的,这里面对头是最大的。
但是我这个I要划过去了,I要加加了I划过去的时候,这个就是所谓的不得不出对,所以这里面两个well是那个单调关系决定的,它必须出对。而这个是相当于时间戳决定的,它必须出对,也就是所谓的不得不出对的问题。
所以这个就是把滑动窗口应用到极致。这里面是说原题有一个是怕超过in。如果它的结果大于等于一个很大的数,这好像是十的9次方,就return1的9次方。😊,这个是题目本身的一个设计。
所以跟这个算法本身没有关系,所以我直接把它列到这了。所以这句话没有什么意义,这个是滑动窗口相关的问题。啊,还有一大类是数相关的。我在数图那一章里面也讲到过,有这么多东西,数的高度,这个是普通数。
当然也有二叉树都可以立 code上也有类似的题目。二叉树的对称判断二叉数是否平衡,二叉数的最小深度,这个其实是最大深度,这个是最小深度,给定一个和求指定核的所有路径以及二叉数和双向链表转换。
包括二叉树的前序中序以及后续便历,这些都可以ON时间内做到。我之前也提到过,因为数比较特殊,它有N个节点,N减一条边,它节点和边是同一个量级的都是ON的,我们对于它做遍历,做什么都可以在ON时间内解决。
那我想提一个比较经典的比较巧妙的,并且不太难的算法,就是求一个无根数的直径,什么叫无根数呢?就是普通的数无向无核图,没有一个节点作为根。😊,那么给定一个无向无环图,就是N减N个节点,N减一条边。
确切的说应该叫无向无环连通图。那求距离最远的两个点,这个求的是两个点,这两个点之间的距离就叫做树的直径,也就是树里面最长的那条边。首先大家可以想象一下,最长的那条边一定是两片叶子。因为如果不是叶子。
还可以再往更长的地方走。叶子就是度为一的节点,相当于可以用它做端点。😊,那比较简单的算法,大家可以想一下它为什么是对的。😊,我以任何一个点为根,我找到距离它最远的节点X,再以X为根。
再找到距它最距X最远的节点Y,那么XY就是一条直径,相当于先找的一个端点,再找到另外一个端点,这两个端点之间就是一条直径。那么如何找到就是距离根最远的节点呢,其实这个就是7。1的内容,它就是数的高度。
因为高度本身就定义为最远的节点。我们现在是变成一个有根数。因为以任意节点为根嘛,然后这个是以X为根嘛,所以求高度经典方法就是DFS不断的做下去,找到最深的那个点就可以了。
所以这个算法巧妙简单就简单在它两次DFS就求出了我们想要的内容,那关键是如何证明大家仔细思考一下。😊,例八也是滑动窗口相关的,但是我把它单独提出来了,因为它和单调队列的关系不大。
刚才那个讲的主要还是单调队列。那这里面因为这个题比较新,是let code上209题,给定一个数组里面全是正整数我标红了,整数不重要。
关键是全是正数再给定一个正整数S求数组里面连续多少个数满足总和不小于S,就是窗口尽可能小的一段,让它总和大于等于S。因为我取的数越多,显然和越大嘛,就关键就是所有数都是正数。
这里面有一个核心问题就是如果一个大的窗口不满足条件,它的任意子窗口也不满足条件。因为显然所有数都是正数。那么我这么多数都不满足,它任意的小一段显然也都不满足,因为全是正的取的少和肯定更小。
那么我们就划这个窗口IJ。如果当前和太小的话,我们就试图增大它就加加J。如果当前和过大的话,我们就试图减小它就把I往右移,所以无。😊,这就是加加A加加J的问题,看一下代码。😊,但如果没解就返回0。
那么我们可以看一下,这里面和不够大,我们就不断的加不断的加J这边。那如果和足够大,我们就不断的把I缩了。那然后这就是一组可能的解更新一下窗口大小,所以也不难。那ON的这种就是复杂度分析可以不讲了。
因为I和J都在不断的增,这个I加加这个J加加从来没有减小过,然后一共也就循环了2N次,所以还是ON的。😊,那这里面我之前讲到过一个类似的问题,就是字符串里面的例四子串变位词,其实跟它意思一样。
也是滑动窗口。我维护窗口里面的字符串的就是字符的个数差。然后lead code上有两个题,一个第76题,一个第三题。其实6题是说找到一个最短的子串包含全部另外一个串里面的全部字母。
这个其实和例四是就和8。2是一个问题。然后无重复子串的最长子串,无重复字符的最长子串就是找到一个尽可能大的窗口里面每个字符只出现一次。同样这个其实也满足我刚才说的那个,如果这窗口太大了。
我们就把左边界往右移呃往右移。如果是右这个窗口太小了,就是里边字符都只出现一次,我们就把右边界往也往右移,就是扩大窗口和缩小窗口。并且也是如果一个这个。😊,小窗口不满足条件。
那么它的大窗口也肯定不满足条件,因为肯定已经有重复了。所以跟刚才讲那个是类似的。刚才那个是如果大窗口不满足,小窗口一定不满足,这个是反着的小窗口不满足大窗口一定也不满足。所以这个都是滑动窗口的问题。
基本上就是一个左边界一个右边界根据不同的条件都在共同的往右滑就可以做了。那还有一类是列表相关的。我之前其实大都提过,只是没有实现。比方说求列表长度翻转翻转有很多种,包括K一组翻转啊。
这是li code上92、25、206题啊,列表的插入删除,有随机指针的列表复制这let code上14720382、83、138题,两个有序列表求交。这个不光是列表。
这个数组什么的都可以做li code上160题找环有没有起点,141、142题倒数第K元素19题。其实还有一个是li code没有的,就是列表判断是否回文,其实我们可以。😊,用对战是一种方法。
还有一种是O一空间的,但是呢要把链表从中间断开,然后把后面翻转一下和前面比较一下。因为翻转我们可以线性时间能做到。啊,最后如果要求不改变这个列表的话,我们还需要翻回去。总之呢列表是一种线性的结构。
我们便利啊插入删除就是增删查改这些操作都可以在线性的时间内完成,这是也是一大类那最后呢是我想讲的就是之前没有提到的问题。啊,第一个就是to sum上最早的一个题。那之所以没有选,就是之前之所以没有讲它。
是因为它需要排序,我不太喜欢排序之后是ON的这个排序要Nlog n嘛。但是呢我们可以用哈西。😊,前提条件是哈希要设计的足够好,所以这种ON就感觉上不是一个绝对的ON。
当然我们一般面试的时候可以理解说哈希足够好,我们对于X查找S减X,那么扫一遍就可以搞定了。所以这个题就迟迟没有讲,只是在这里提一下,用哈希的话,可以在ON时间内做到,或者这个数组本身是排好序的。😊。
那么10。2是其实是之前google的一个面试题。给定一个1到N的排列,就是一串数。我们每次可以选一个数,把这个数啊放到末尾,当然或者也可以把它放到开头,放到哪儿都可以。😊。
那我们至少要操作几次才能把它排好序。看起来这个问题很难。我们可以仔细分析一下,我们一其实没有必要动,因为没有理由动一,我们把二到N都排好了,一自然就排好了。那如果我们要移动X,我们决定把X放到末尾。
因为我们操作只能放到末尾,要把X放到末尾,必须在它之后把X加1X加2以及N都放到末尾,因为没有办法,那些数它放到末尾,它就是最后一个了,那些数都在它前面,我们必须要把这些数都放到末尾。那么。😊。
言外之意就是一到X减一都是有序的。我们的目标其实是找到尽可能大的一个X,然后让前面那些数,当然中间可能加杂别的数。但是无论加载什么数,一到X减一那些数,从左到右都是按顺序出现的。然后呢。
我们把这个从X到N那些数都把它移动到末尾,总体移动了N减X次,那么其实我们这个就这么做。当然这里面X和w差了一个一,我们就看一下,现在想要找一w等于一嘛,看看能不能找到一找到一了。
我们看一后面能不能找到2,就是我们按顺序看,最长能找到多少个数。那么从这个w到Nw是第一个没找到的数嘛,因为w不断的再加,从到N就必须要一个一个的移动到末尾。所以这个看似复杂的问题,扫一遍。
看看有多少个数是按顺序出现的就可以了。😊,那这个题呢其实跟刚才那个题差不多,是摩根斯坦利的一个一个比赛题。但是我把它简化了,本质就是也是这样。它呢操作是既可以把它放到开头,也可以放到末尾,跟刚才类似。
刚才只能放到末尾,这个是可以放两头。那么我们的操作其实是我们要把一到Y放到开头。当然这个是按倒序,我们要把Y放到开头,Y减一放到开头,一直到一放到开头X那边也是类似的。我们把X到N一个一个的放到末尾。
那。😊,言外之意就是X加一呃,这个Y加一到X减一中间那段是有序的。如果这段是有序的,我们就可以把这这部分移动到开头,这部分移动到末尾就变成了一到N啊。😊,跟刚才类似。
我们但是我们需要统计一下哪些数是按顺序出现的。我们用一个动态规划的算法,用DPX表示从X开始,就是X这个位置开始往后。😊,有多少个数或者说有多长的数是按顺序出现的。
比方说DPX就表示XX加一一直到X加DPX减一是按顺序出现的。有这么长,从X开始有这么长的数是按顺序出现的,在元数组里面,那么倒着循环I其实这样有这么一个式子存在,要AI是连续出现的。
我们就要看一下AI加一有多长是出现的,那么加上去就可以了。那前提就是如果没出现的话,这个东西是0。比方说AI是目AI加一没有在AI的右边的话,我们认为这个数是零,所以我把初值负成零了。
那并且我们是倒着循环的。因为这个数是就是我们是用大值推的小值嘛,所以倒着循环I。那么这样弄完之后,我们就知道。😊,从AI开始最长连了多少段,我们的目标就是从中间找到尽可能长的一个段嘛。
然后我这里面就相当于用这个数组记录了最长的那个段,最后在M里面,那么就返回N减M,就中间这段是不用动的,剩下那N减M的时候必须要米一道开头要米一道末尾。所以看似很复杂的一个问题。
我们都可以ON时间内做到。😊,只不过这个还用了ON的空间。那上一个问题是O一的空间。啊,思路是类似的这是一个动态规划的思想。大家可以仔细的体会一下。那结束语其实还是老生常谈了,就是ON是一个很神奇的。
这个可以说是一大类问题,大家要多思考,勤练习,多写代码,多实践。好,今天的课就到这里,谢谢大家,欢迎大家给我提出批评指正。😊。
人工智能—面试求职公开课(七月在线出品) - P4:阿里巴巴面试题精讲 - 七月在线-julyedu - BV1Xf4y1r74s
我们这堂课的主要内容是阿里巴巴面试题精讲。
我将从如下几个方面讲述本课,先讲一下关于面试的一些观点,然后讲一下笔试面试题的特点。然后呢我会讲。近些年来,阿里巴巴的7个例题,这是从70多个笔试面试题里面精选出来的,大概属于四个方面。两道题属于概率。
一道题是智力题,还有三道题是我们最重要的数据结构与算法。最后一个题呢是一个开放性的和算法相关的实际系统的问题。然后做一下总结,结束本课。😊。
首先,关于面试。之前我也讲到过,到底各个公司有没有自己的题库。其实呢这不是一个很重要的问题。因为即使有题库,这些题也是共享的。他们的题目来源无非就是要么就是员工出的题,要么就是通过网络自己搜罗来的题。
所以没有说这个题被某个公司面过了,就不会被另外一个公司面。所以说我们不要把这个题打成一个标签,它是公公司A的面试题。那个题呢是公司B的面试题,没有这样的标签存在。这个题既可能被公司A面过。
也可能被公司B面,可能被他们同事面过。还有一点,我想说一下,就是笔试和面试。那笔试呢大家都知道,发些卷子闷头写就可以了。它是一种没有交流的这么一种笔试。那么。😊,我们写题目可能写程序的题目相对少一些。
偶尔会有这么一两道,大部分都是填空啊,选择啊,大题无非就是写写思路。因为呢。判卷子的人是没有办法对我们的程序正确性做出判断的。特别是有些人代码可能会写的很乱,没有交流,很难被人看懂。那么题型非常丰富啊。
有很多填空选择判断等等这样的问题。那面试呢大家也很熟悉,他和笔试最大区别就是它是有交流的。你需要和面试官面对面的交流。所以呢面试通常会要求你一些完整的代码。一旦有些地方他看不明白,他可以问你。
你可以给他讲,这也是你展现自己思路,表达自己思想以及体现这个表达能力的一个很重要的机会,所以笔试和面试是不一样的。😊。
那笔试题和面试题有很多特点。目前从阿里巴巴的题目上来看,我觉得。😊,它非常重视基础知识,尤其是笔试题型非常多啊,包括填空选择等等。这些题涉及的面呢非常广。比方说操作系统它可能涉及到这种缓存啊。
LRU这种替换算法呀,进程现成的概念啊,死索有哪些条件如何避免啊等等这些基础知识。那网络呢比方说TCP协议以及三次握手的过程啊,还包括比方说你在浏览器里面输入一个网络地址,接下来发生的事情会怎么样。
或者说操作系统里面,你在键盘上敲击一个键,或者说点击下鼠标,后面将有哪些操作呀等等这些事情。那数据结构与算法当然是最重要的。包括我们大家都熟悉的排序啊,而分查找啊,数据结构里面比较重要的就是数和图啊。
当然还有我今天要讲的最后一个例题,就是实际系统的一些设计算法的开放性问题。那笔试啊。😊,或者说面试可能还有一些数学问题,或者说智力题主要体现在概率和组合数学里面。
那下面我们就进入正题来讲这个七个例题。我在每个例题后面都加了括号,体现了这个例题的分类。比方说这个题是属于概率的,它是说有8支球队采用抽签的方式随机配对,也就是两两配对。然后呢这样形成四对儿。
那么这四对比赛,假设呢其中有三支强队问。😊,出现强强对话的概率。什么叫强强对话呢?就是两个强队分在一起,比赛的概率有多大。那这种问题呢可能是一个填空题,也可能是一个选择题,不是很难,大概思路就是数数。
它是组合数学相关的概率问题,怎么数呢?比方说当然说这个题有很多种做法,我只讲其中的一种,比方说我们不考虑强队。现在就是说8支球队,我们把它两两配对有多少种情况呢?我们可以这么考虑。
我们随便拿出一支队伍来,因为一共有8支球队,我拿出一支来还剩7支这7支他可以任选一个对手配对,所以它有7种选择。😊,那剩下的呢还有6支球队一样的,再拿出一支来,他有5种选择对手的情况。
然后再剩下还有4支球队,再拿出一个来看三种选择对手的情况。那么再剩下的两支球队,他们只能互相配对了。所以这个8支球队两两配对的情况说是根据乘法原理是7乘以5乘以3乘以1,这个是105。
这里面其实是可以推广的。如果是这个N支球队,当然N是偶数了。它这个两两配对的可能性,其实就是N减1乘以N减3乘以N减5乘以N减7,也就是每隔一个乘以下直到一这个是两两配对有多少种可能。
那么现在我们还没有考虑这个强队和弱队之间的区分。那么现在我们来考虑。😊。
我们反方向考虑,假设每个强队都分到了一个弱队,也就是三个强队没有相遇,那么有多少种可能呢?那么就是从5个弱队中选出三个跟他们配对就可以了。那注意这个是有顺序的,因为三支强队是完全不一样的。
所以呢我从5个弱队选出三个跟他们做一下全排列就可以了。那剩下的呢还有两个弱队,他们自己匹配,这是那个乘以一的来源。所以呢这一共是60种情况。那么105种情况里面有60种情况是没有强强联合的这么一个。😊。
情况数。所以说有45种情况是强强联合的,也就是强强对话的这么一个方案数。那么概率呢概率其实在这道题目里就是分子分母相除,一共有105种情况是全部的情况,有45种情况是强强联合的情况。
这么一除就是7分之3。那么做一个小总结吧,这种概率题目通常是利用组合数学的公式,计算出方案数,这个方案数分别就是计算一下分子,计算一下分母。当然这里面有技巧。
可能有一些我们可能反着算总体减一下会好算一点都能。但总的来说都是套用组合数学的公式,分别计算出分子分母除一下,得到的这个概率。😊。
啊,比较简单,我们再来看第二个例题。他是说有两个包或者说两个口袋,甲包里呢有8个红球,两个篮球。乙包呢反过来8个篮球,两个红球。那先抛硬币,注意这个硬币应该是均匀的,也就是正反面的概率各是2分之1。
我们抛一次硬币决定是选择甲包还是选择乙包。当然,一旦确定了选择哪个包,另外一个包就没有用了。我们从这个包里。
取球每次取一个,并且放回,一共取了11次。注意这是一个有放回的。那么11次的结果恰好是七次红球,四次蓝球问。最开始我们选中甲班的概率啊,它当然也是概率相关的那这是一个后验概率的问题。什么叫后验概率呢?
就是已知了结果。😊,再问我们最初某个事件的概率,这个是在知道了这个结果下的,或者说这是一个条件概率。那条件概率我们就要用条件概率的解决办法,主要呢就是贝斯公式。
我们定义事件A是最开始选了甲包。事件B呢是最开始选了乙包。事件C呢是这十一次取球,恰好是七次红的四次蓝的这么一个事件。😊,这ABC定义好,那么显然PA等于PB等于0。5。
因为我们最初是抛硬B决定的选择哪个包,那么它们的概率是相同的。那么关键是这个C怎么算?那C我们用条件概率算,假设我们已经知道我们现在选的是假包,那么发生事件C的概率是个什么呢?
因为那个放球是一个这个有放回的这么一个抽样,它是一个二项分布。每一次都是。😊,以0。8的概率。出现红球0。2的概率,出现蓝球,这个是和这个袋子里面的球数有关的。因为是8个红两个蓝。对于甲班来讲。
所以是0。8是红,0。2是蓝。那么前面那个组合数呢,就是我在这11次里面,我选择出4次,让它是篮球就可以了。当然也可以写成C117,这个答案是一样的。因为11个里面选4个和选7个是一样的。
那么对于乙班也是类似的,这是低问B出现C的概率,注意这是两个条件概率。😊。
那我们求的是什么?求的是已知C,然后出现A的概率,也就是givenCA的概率。那么根据贝斯公式,它是这么一个东西,就是givenAC的概率乘以A的概率除以C的概率。
注意这里面第一个是已经能求出来的PA呢是0。5也是知道的。我们唯一不知道的就是这个PC,也就是C的概率,C的概率怎么算?再根据贝斯公式展开。😊,分子没有变化,关键把分母展开,展成什么呢?
因为C无非就是A成立的时候,C的概率和B成立时候C的概率。因为前面选班的时候分A即B嘛,所以把所有情况都没举出来,这个又是一个思公式。我把这个东西乘以givenAC的概率以及PB乘以givenB的概率。
这两个加起来就等于所谓的PC那现在这里面所有的值都是我们能算出来的,这里具体算我就不算了。但是PAB是0。5,这个P givenAC的概率是这个P givenBC的概率是这个这个也是前面已经算过的。
这个也是0。5,所以所有的数我们都可以算出来。当然这个概率我们就能算出来了,也不是很难的题。😊。
然后呢,我们再看一个智力题。在黑板上写下1到50这50个数。然后呢,接下来我们有49次操作,每次操作都是选两个数擦下去,换上这两个数的差,注意这个差取得是绝对值,也就是以大数减小数的结果。
每次选两个数擦掉放上去一个数,所以每次。😊,之后就减少了一个数,这样49次之后就只剩下了一个数,问剩下的那个数可能是什么?为什么?😊,我们先考虑把这个问题简化一下,先不考虑剩下的数是什么数。
先考虑剩下的数是奇数还是偶数。我们可以考虑有什么东西是不变的,因为这里面的数不断在变。我们考虑一下什么东西不变。剩余奇数个数的奇偶性不变,什么意思呢?
如果我们选的A和B是两个奇数,我们把它们擦掉了,然后换上他们的差,他们的差显然是偶数。那这样看来,奇数的个数是减少两个了,因为两个基数擦掉了,换的一个是偶数。😊,如果我们选的两个数是偶数。
它们的差显然也是偶数。那么把它们擦掉了。😊,这个基数的个数是没有变化的,换上来的是不是也是偶数。所以总体来讲,基数的个数是不变的。😊,那如果第三种情况,我们选择两个数,一个是奇数,一个是偶数。
那么把它们擦掉,换上的结果是它们的差,奇数和偶数的差显然是个奇数,所以擦去了一个奇数,一个偶数,换上来一个奇数,这个奇数的个数也是不变的。所以无论哪种情况,要么奇数不不变,要么奇数的个数减少2。
所以奇数的个数只能两个两个的减少。😊,那总体上50个数有25个奇数,25个偶数,那奇数的个数是奇数,它两个两个减少。所以说最后剩下的一个数只能是奇数,不能是偶数。因为如果最后剩下数是偶数的话。
说明奇数减到了0个。但是奇数一上来有25个,两个两个减少不可能减到0个,这我们就证明了剩下的数一定是个奇数。😊,那么剩下的数可能有多大范围呢?首先因为我们换上的是两个数的绝对值。
所以这个一定是大于等于零的那并且它显然也是小于等于50的。所以最后数的范围一定不超过50,不超过50的基数是不是都能出现呢,这就需要我们构造一个过程,看看假设我们想最后得到一,我们应该怎么做。
可以让它最后得到一,或者说我们可以构造出一个过程,让它最后得到一或者说最后得到3。😊。
请看这样的构造过程。如果我们最后想得到一,我们就把一和二拿出来。因为2减1等于1嘛,这两个数我们暂时不动,我们这样做,把三和四配对擦掉,它们换上一个一5和6配对擦掉,它们换上一个一这样一弄。😊。
一直到4950,这样之后就变成了这个12,我没有动,后面跟了24对一,也就是这个24个一。因为24对的答案都是一,有24个1,24个1,我们两两相消,最后会变成这个全都变成0,应该是12个0。
那些零无论怎么消,最后就会变成一个0。然后这个二减1,最后变成一个一,然后和那个零一消就变成一了。所以关键是我们拿出一个东西得到我们想要的结果,然后后面那些数把它们变成相等的,最后变成零消掉就可以了。
那假设我们想得到三呢,假设我们可以拿出一和4来。😊,因为4减1是3,剩下的也一样,两两配对又得到一大堆一,最后又消成零了。假设我们想得到5呢,我们就拿出一和6来。然后后面配对注意把6跳过去。
这个是把四跳过去。那类似的假设我们想得到49呢,我们把一和50拿出来,把他们最后再消前中间的那些呢,又是两两配对又是得到这个24个1。😊,所以都是类似的。根据我们这种构造方法。
最后我们可以得到1到49这全部的基数我们都可以得到。因为我们刚才已经证明了答案只能是基数,现在我们又证明了我们可以构造出过程,把这些基数。也就是这25个基数,我们全都能构造出来。
所以说最终的答案可能是1到49之间的全部的基数。😊,这个是我想讲的第三个问题,下面进入这个数据结构与算法的问题。
第四个题。从无序的实数数列里面。求里面大小相邻的实数的差的最大值,要求线性的空间和线性的时间。我先解释一下这个题,什么意思?就是说给你一串数。😊,如果呢你把这串数排好序,或者说把这串数画在了数轴上。
其实跟排好序的意思是一样的,求相邻两个数的差的最大值。大概是这么一个问题。显然呢排好序是一种方法。当然,排序是N log N的时间复杂度。那其实在这个lead code这个网站上,164题就是这个问题。
只不过它里面的数不是实数,是整数了。我们来讲这个版本,思路是一样的。😊,我们假设这串数里面最大的是max最小的是 mean,并且假设它们两个不相等。为什么假设它们不相等呢?如果所有的数都相等。
那么相邻两个数之间的差显然是零,答案也就是零了。这个是比较简单的结果。那如果不相等,也就是说max不等于命。我们把命到max之间的这个区间分成若干个统,什么叫统呢?也就是统排序的思想。
我们把这个 mean到max之间平均分成N加一份。😊,每一份是一个区间,每个区间我们把它看成一个桶,也就是说一个桶和一个区间或者说一个子区间是等价的概念。当然有一些细节我们来看。
每个桶的宽度当然是max减面除以N加1,因为分成了N加一个桶。那么每个桶我们可以认为是一个左臂右开的区间,为什么右边开呢?因为这个开区间和下一个桶的左端点恰好重合,我们要保证一个数只属于一个桶。
那么显然这个应该是一个左臂右开的这么一个区间。那注意呢,最后一个桶是特殊情况,最后一个桶是双臂区间,因为那个max右面没有值了。😊,啊,这个其实开和B区间并不影响结果。
这里面是为了这个细节或者说清晰在这里面强调一下。那么。我们分桶的目的是什么呢?我们这样把一个区间分成若干个子区间之后,首先区间是等宽度的。另外一个每一个数属于且仅属于一个区间,它们之间是不交的。
那么最小值在第一个桶里面,为什么呢?因为最小值就是第一个桶的左端点嘛,第一个区间的左端点,最大值呢类似的它是一个双臂区间,最大值是最后一个区间的右端点,所以它在最后一个桶里面。
那么还有一个也就是割隆原理或者说抽屉原理是说我们把N个数放到N加一个桶里面,至少有一个桶是空的。因为桶多数少,不可能每个桶里面都有数,至少一个桶里是空的是什么意思呢?😊,也就是说中间可能有个桶是空的。
什么叫中间呢?我是想说这个桶的左边儿。一定会有数,这个空桶的左边空桶的右边一定也会有数,为什么呢?因为我们第一个桶不是空的,最后一个桶也不是空的,空桶肯定在中间,所以空桶的左右是都会有数的。
不可能空桶左或者说空桶的右边是空的。因为它一直是空就会走到左边第一个桶里面,一直是空就会走到右边最后一个桶里面。所以空桶的左右都有数。这个结论有什么意义呢?😊,首先我们知道同一个桶。
也就是同一个区间里面的数,任意两个数的差都不会超过区间的宽度。因为数的大小在那摆着了。我们在这个桶里面最小值也就是桶的左端点,最大值也就是统的右端点,最小值和最大值的差无非。😊。
最大最大了也就是这个桶的宽度。但是呢我们又知道有一个桶的存在,一个空桶的存在。那么这空桶两边左边第一个数和右边第就呃左边第一个数和右边第一个数,它们之间的差值一定大于等于这个桶的宽度。
因为中间那个桶空了嘛。左边那个数和右边那个数的差肯定比这个桶的宽度要宽。😊,于是我们就说同一个桶里面的数是没有意义的,我没有必要统计同一个桶里面的数。因为同一个桶里面的数差值不够大。
我们至少找到了空桶左边那个数和空桶右边那个数差值比这个同一桶里面的数大。所以我们对每个桶只记录最大值和最小值就可以了。我们用这个桶的最小值和它前一个桶,当然我指的是前一个非空的桶的最大值。
这个差值量量比较一下就可以了。所以说我们在分桶的时候,实际上少考虑了很多情况。我们对于每个桶只记录了一个最小值和一个最大值就可以了。那我们先来看看这个具体实现。这个是我在let code上实现的代码。
因为它都是整数有一些溢出的问题,所以这个代码看起来略微有点长。最关键在这儿。😊。
这个是maxine,这个是mini,就是我刚才说的max min,我把它分解成N加一份儿,每份的宽度是德尔ta。那么。😊,这个是我用整数计算,因为避免了浮点数的计算。这mt就是两个做乘法。
计算出这个第I个数,也就是那么I应该在哪个桶里面,它应该在哪个桶里面呢?它应该在那么I减咪咪乘以N加一除以max减幂这么一个桶里面。这个是把某个数映射到了它所在桶的编号。那么它所在桶的编号。
我就可以在这个编号里面求出这个桶里面的最大值和最小值,注意这个桶有可能是空的。如果是空的的话,最大值最小值都是这个数。如果不是空的的话,最大值取更大最小值取更小。所以这一重循环下来。
我就求出来每个桶是不是空的,并且如果不是空的,每个桶的最大的值和最小的值,我们都求出来了。根据刚才的结论。😊,这个最大的间距不在同一个桶里面出现,那么我只看相邻那两个桶,怎么看呢?再循环一遍。
如果不是空的的话,我们用当前筒的最小值减去前一个桶的最大值就可以了。注意这last表示前一个非空筒最大值。😊,那么最后return answer就可以了。那实际上这里面当然前面有一些特殊的处理。
如果个数不足两个以及这个max等于面,这些都已经特殊处理掉了。所以这个题目是利用统排序的思想做到了ON的时间复杂度和ON的空间复杂度。因为我们开了三个数组。
空间复杂度是ON的循环呢这个求最大值最小值循环了N次。然后分筒。😊,并顺便计算最大值最小值又循环了N次,以及最后就是。求得结果,把每个桶的最小值和前一个非控筒的最大值做减法又循环了字。无论如何。
它是个线性的算法,这是非常巧妙的这么一点,大家仔细理解。😊。
那么第五题呢,它是一个随机采样的这么一个问题,说的有点啰嗦。我觉得这个题简化起来来说,首先它是一个数据结构与算法的问题。然后。😊,我们有这么一个函数,它是get name。该 name干什么呢?
是我可以返回。这个数组里面的一个数就是一个一个返回。也就是我没有办法通过下标得到数组里面的每一个数,我们只能每次get name一下,或者说get next了,我们只能拿到下一个数。
当然如果没有下一个数返回not,这个可能是java的习惯,或者就是一种伪代码的习惯。因为这个int值是不能返回not的,java当然能返回 now,但是但是是小写的这种not。
并且这个应该是integer。所以我说这个题目,这个函数头啊以及等等,出的并不是很好。所以我后面写的是一个伪代码。😊,然后要求什么呢?要求我们从这个数组里面随机的选择出一个数。纯随机。
也就是每个数选择的概率是相同的,各是N分之1。当然这个N是未知的。其实呢这个题我在概率的那个公开课里面,或者说短视频里面也讲到过,它是一个流式的数据。他说了这么多,就是想说这个数据是一个流式的。
什么叫流式的呢?就是我没有办法,或者说没有必要,或者说不允许把所有数据都存下来,数据是一个一个流过来的。我们可以get next的得到下一个,但是我们没有办法把所有数据都得到。
当然它要求的空间复杂度是常数的,也不能让我们把所有数都存下来。那么这是一个蓄水池,或者叫水库抽样的一个经典的应用。什么意思呢?😊。
我先说算法,也就是不断的get对于第I个元素,我们以2分之1的概率选择它就是这么简单的一个算法。什么意思呢?就是我们先选择对于第一个元素,我们以概率为一选择它,就是我们先选择了这么一个数。
对于后面的数呢,每来一个数,我们就以2分之1的概率要它要它的话,我们就把之前选的那个数扔掉,就换掉了。如果不要它就放弃这个数还保留我们之前选的那个数,就是这么简单。
那么怎么证明它确实最后选择每个数的概率是N分之1呢?😊,我们先说对于第I个元素,无论之前。选了哪些数?我们再到第I个元素这一步,选择第I个元素的概率是I分之1,这个是算法决定的。那么。后面第M个元素。
也就是M大于I的时候,不选择DM个元素的概率,显然是M分之M减1,因为只有M分之1选择DM元素嘛。那最后我们能选择第I个元素,并且真的把它保留下来的元素就是在第I个元素的时候。
我们选择了它走了I分之1这个概率。后面元素我们都是走的这种M分之M减一的这概率,因为后面都没被选中,才不会换掉第I个元素。那我们把它乘起来,注意这个这一项的分母恰好是后一项的分子。
这样就所有的一项和后面一项就消消掉了。最后只剩下第一项的分子和最后一项的分母,所以说我们最后能保留下来第I个元素的概率,恰好是N分之1。😊。
注意这个I是任意的这就证明了我们这个算法可以等概率的返回任何一个元素。这个算法非常简单,并且非常好。它不需要预先把数据存下来,而且我们不需要知道这个N等于多少。
我们只要对当前第I个元素以2分之1的概率保留就可以了。
我看看这个。代码也非常简单,这是一个伪代码。注意这个我们假设这个东西能返回到,或者说假设比方说有一个特殊值,我们一读到它就认为停了。当然这I从一开始。😊,什么意思呢?我们不是说以I分之1的情况下。
以I分之1的概率保留第I个元素嘛?那么我们产生一个随机数,假设这个随机数是均匀的,它对I取域数,对I取域数有I种情况,也就是0到I减1。那么当然这可以写任何一个数,且0到I减一的任何一个数。
那我们就选择了0,因为I最小可能得一嘛,所以我们这个就选择零是最好的。😊,也就是说。对I取域数有0到I减1这I种情况,我们只取了0。如果它对I取域数得0,实际上这个概率就是I分之1。
我们以I分之1的概率保留比I个数也就是X。剩下的数我们都就是其他的概率,我们这个result保持不变,注意I等于一的时候,我们以百分之百的概率接受了这个X。那么当然后面有可能换掉。根据我们刚才的证明。
最后这result可以是任何一个数,并且是任何一个数概率是相等的。这个是一个非常经典叫做蓄水池或者叫水库采样的这么一个方法,它是线性的,并且是常数空间。因为我们没有空间来把所有数都存下来。那注意。
这个方法是可以扩展到要采样K格的一般情况的。K格的时候,我们就用一个数组来把它保存下来,然后换一下那个下标就可以了。这个大家可以思考一下具体怎么做。这个题实际上是K等于一的。😊,一个特殊情况。
这个是可以扩展的。这个是我想说的第五个例题。
第六个例题我说的快一点比较简单,它是数组查找,它是从AI这么一个严格递增的整数数组,注意是整数数组必须是整数,浮点数是不一定对的。从这个整数数组里面找AI等于I是否存在这么一个下标,AI等于I。
当然要分析什么时间复杂度啊等等这些东西。数据结构与算法,它也是数据结构与算法题。那首先呢因为我们要查找这个index,我们不知道它等于多少。注意啊。
这个不是在AI里面找到一个值X给定一个X找这个是我们要找到一个index就是一个下标,下标值和这个数组在这个位置值是相等的。我们不知道I等于多少,所以我们不好二分,实际上是有二分的办法的。
我们把它变一下。😊,假设我们有一个数组,BBI等于AI减A。那我们看一下数组B具备什么样的性质。首先我说它是单增的,我指的单增是不一定严格单增,也就是有可能相等,它是后一项减前项是大于等于零的。
为什么呢?我们减一下BI加一减BI根据定义最后是这样的AI加一减AI减1,注意AI是一个严格单增的整数数组,所以AI加一减AI要大于等于一。因为这个它不可能相等,而且又是整数那么差值要大于等于一。
所以它减去一是大于等于零的。这说明。😊,BI是一个单增的,注意是不一定严格单增是大于等于0,有可能相等。那么我们要找AI等于I,相当于找BI等于0。
那么我们相当于在一个严格呃在一个不一定严格单增的数组里面找到零值,那这是一个非常简单的二分查找。因为就是在一串单增的数里面,看看有没有一个数等于0。那么显然它是一个logN的时间算法。
这就是最朴素的二分,所以我没有写代码,注意这里面这个B数组我们不需要预先求出来。我们就对2A2分在二分的时候把它减I就可以了。因为我们算B的时候是需要ON的时间复杂度的。我们不能把B算出来。
所以这个B是一个隐含隐式存在的。所以我们通过这个二分查找算法,在B数组里面,或者说在AI减I里面找到零值,就是我们想要的。😊。
我们再看一下最后一个题。最后一个题我觉得我也是给大家讲呃讲一下思路,也就是这是一个开放问题。我我讲一下这个我从哪几几个角度来考虑。首先有一批数据,百万级别,我不知道这个题是哪年的题。现在看来。
百万级别并不是特别大。那么有什么呢?😊,有用户ID科目ABC等等成绩。然后用户ID呢是0到1000万,并且是连续的。然后可以唯一标识记录。然后成绩呢在0到100之间,2块磁盘内存有这么大。然后呢。
有三问。第一问呢,要查询ID对应的各科成绩。然后第二问呢,这个ID在0到10亿之间,它把ID改了,原来是1000万,并且呢是不连续的,怎么办?第三问呢。除了要查询这个成绩以外。
还需要排序或者说排名怎么办?大概是这么一个问题。这个呢是我选做实际系统的这么一个例题。我觉得这个题可能是一个面试题。如果是笔试的话,也只是写写思路。因为这个题我觉得是一个非常开放的问题,做法可能很多。
我只是这个提一下我的一些考虑,可能不是最优的。欢迎大家提出这个批评指正吧。首先ID连续那非常简单,可以用数组存,因为ID是连续的嘛,0到1000万,无论是多少,这个数据只有100万条。
我们把这个ID最小的那个拿出来,都和最小的ID1减,就可以把它变成0到100万左右就可以了。因为这个呃无论从哪个ID开始,反正它是连续的一段,就跟从零开始连续的一段一样。那么们直接用数组存。😊。
那数组存相当于存300万个int,300万是多少呢?就是3兆个int,3兆个int,一个int是4个byt,所以大概12兆的内存就够了。这个直接放到数组里面,内存够用。那如果ID不连续呢。😊。
我们需要,并且这个ID的范围那么大,有1到呃0到10亿之间。所以我们需要把ID映射成这个。
一个index,那么怎么映射呢?我们当然需要map或者哈希。那关键是啊如果我们把它放到数组里面还是12兆,那关键是这个ID怎么映射映射,我们要写一个哈希。这个哈希呢有key和value。
它的value呢其实就是。😊,大概100万个in。100万个int呢其实没有多大,100万个int大概是4兆。因为300万个是12兆嘛,100万个是4兆左右,4兆左右呢。
我们再存这个就是假设我们给他这是多少,120万吧。1200万个。因为这是300万,我们取4倍,1200万个K,也就是我们把哈希空间变成1200万那么大。然后大概这1200万大概需要48兆。
再算上这12兆,一共需要60兆空间,什么意思呢?我们哈希呃我们不考虑这个哈希函数具体怎么建立,我们哈希给他1200万的空间。😊,1200万个int的空间。然后来一个int。
我试图把它映射到0到300万之间呃,0到100万之间。具体哈希哈数怎么设计,这个大家自己仔细讨论,但是光靠哈希的空间和这个整数数数组的空间应该是够用的。大概一共60兆空间可以解决这个问题。
当然其实这个题做法还有很多。比方说我们可以这个在磁盘上做哈希啊,或者把一个int映射成为磁盘空间上的一个这个地址这么一个记录的地方。然后我们从这个文件里面把这个人的三科成绩拿出来等等等等。
这个做法非常多,但是只靠内存的话,因为主最关键问题是这个哈希的空间不好算。我们如何把这个不连续的空间映射成为连续的空间,需要一个非常非常大的哈希表,这里面大概1200万,如果只用内存的话。
当然我们可以考虑在磁盘上做映射。那这个效率会低很多。😊。
那么第三个关键是如何对100万的数据做排序。因为他说的这个需求不是很明确,是单科排序还是总分排序还是怎么排序。如果是总分,或者说每一科每一科之间排,那是对300万的数据做排序。那无论如何都要做排序。
当然还是需要哈希表,因为我们需要把这个不连续的key或者说0到10亿的key映射成为0到100万左右。这个需要一个非常非常大的哈希表。刚才我说了1200万左右的哈希表,也许够用,也许不够用。
这个我觉得在实际情况中需要考虑很多问题。那不够用的话,就像我刚才说的,需要在磁盘上写一些东西。😊,那并且呢这个我觉得主要考的是排序,因为他要找到每个用户的rank。也就是排排名值。
那排序就是经典的啊外部排序,外部排序是怎么做的呢?我们先把数读到内存里面来,然后做好排序。操做好排序之后呢,我们把它写到文件里面,然后把所有数一部分一部分的读到内存里面,排好序,写到文件里面。
然后写到文件里面之后呢,再对这些文件做规并排序。也就是说我们用文件作为了一个临时的缓冲区,然后做排序具体的细节需要大家考察一下外部规并排序的这个具体做法,然后我写的这比较简单啊。
一般就是按内存做排序写到文件,然后文件做规并。排好序的数据,我们就可以得到它的rank值。😊,然后得到ra值,如果就是。数据已经排好序了,最后我们还是可以存到内存里。因为刚才是300万。
现在无非就变成了400万。因为三门成绩再加一个rank,即使再算一个总分,也不过是500万的数据。500万个int其实内存是够用的,并不很大。因为刚才300万我们只用了12兆嘛,所以并不是很大。😊。
那么有些优化思路,那比方说各科成绩0到100,我们当然可以考虑压缩。因为刚才说的我们全是按int32Bt做的32B其实可以存到呃十的9次方,也就是10亿级别的数据,那么只0到100。
当然我们可以把它缩成chair这样使用的空间就少了。当然还有其他的压缩办法,比方说相邻的两科,我存一个偏移量,比方说1个90分,1个100分,当然我可以存1个90,再存一个正十就可以了。
当然这个可能并不能减少多少空间。那当然还有其他的压缩办法。比方说把它压到二进制里面。因为这个100大概是占这个7位到8位的样子。那么一个int其实可以存三门到4门课程的成绩。所以。😊,我们这样做的话。
就是存储量其实可以减少一个常数的级别。然后呢,排序的策略当然因为所有成绩都是0到100,即使我们算总分的话,也不过300分,我们可以不用排快排,可以用这种技数排序。因为它是对这个呃。整数是有范围的。
只有300这么大,非常小。我们可以用计数排序来代替快排,这样可以提高这个时间呃这这样可以降低时间复杂度,提高时间效率等等等等。所以我觉得这个题是一个非常发散的问题,我也只只是给大家提出一些思考的方向。
这个具体哪些结果孰优孰略,大家自行评判。😊。
那么我做一下总结,刚才其实已经提到了,笔试非常注重基础,因为它的题型非常多,这个面非常广。比方说操作系统啊、数据库啊,这个嗯算法呀等等等等。那面试呢当然是注重交流,我们千万不要把面试当成笔试。
这个我反复强调过,因为。😊,面试官在等着你跟他交流,你即使写程序,你要说我现在为什么要写这个东西,我总体思路是怎么样的。我下一步打打算做什么,以及一些t case,可以给出来,尽尽可能给。
要给面试官展现自己积极的情绪。那还有刚才那个题我不知道是笔试还是面试,有很多题目是没有标准答案的,它是开放问题,更需要你去拓展思路去交流。好,多做假设简化问题。因为这个有些问题可能比方说给你一个二叉数。
然后让你求两个节点的最近公共组监,然后你可能要做一些假设,比方说二叉数有指向父亲的指针,这样你做起来就会很省事。如果没有就不省事。所以有些东西你可以自己假设,然后跟面试官说,我做了这样的假设。
然后我写这样的程序。然后这个当然这个这个程序包括这种函数的头部要自己定义写出,这个跟你做的假设也是有相关的。那当然还有一还有一点就像刚才那些智力题。😊,是没有固定套路的这就需要我们多总结,多思考。
多归纳。
好,今天的课程就到这里,谢谢大家,欢迎大家给我提出批评指正。😊。
人工智能—面试求职公开课(七月在线出品) - P5:曹博:我的北美求职心得 - 七月在线-julyedu - BV1Xf4y1r74s
🎼。欢迎收看7月算法公开课。我们本堂课的话题比较轻松,主要内容是我的北美求职心得。我将从如下几个方面讲述本课,先讲一下一般流程,然后讲一下公司的列表,再讲一下公司招聘的烦恼,然后讲一下签证的问题。
总结一下国外面试的题型以及如何准备,再给一些例题,最后总结结束本课。关于流程啊,投北美的职位流程其实和国内也差不太多,一般有如下几个渠道来投简历。
首先可以通过link inlink in有很多recruiter,也就是可以理解为HR之类的人,他会主动联系你,或者你主动联系他们,然后通过link in站内线互相交谈,然后可能会电话联系。
最终可以投简历。那当然还有一种就是直接投,直接投的这种成功率比较低。因为现在公司的candidate都比较多,所以直接投简历往往就会很有可能石沉大海就没有任何消息了。也就是可能最后被默具了。
那比较好的途径,我觉得还是link in最好途径其实还是找内推。因为如果有一些你的好朋友或者什么认识的人学长之类的,在你想去的那个公司他可以推荐你这样公司对于推荐的重视程度也比较高。
所以这种给你面试的可能性也比较大。然后还有一种途径,这个相对比较难,就是通过比赛。因为很多公司在比方说,原来叫inter straight,还有code forces。
还有这个top code等等这些网站上嗯,会挂一些题目做一些这个比赛,如果你达到比赛,比方说前十前20的这种名次的话,可能公司会联系你。因为他们本身就是想。通过比赛发现一些人才。
这个是我大概总结的四个投简历的这种方式。其实对于我本人我比较喜欢还是这种内推。因为link in的这种成功率也不是特别高。尤其是如果人在国内的话,嗯,可能也不太会有很多recer联系你。
因为我有很多朋友在国外的公司,所以我当时投简历选择的就是找内推这个途径。然后之后就会被公司的HR联系。这个联系一般也就是1个10到20分钟的这种谈话,了解一下你的背景啊,曾经有什么项目啊。
然后想做一些什么事情啊,包括你熟悉的语言啊等等,然后可能给你介绍一下公司的概况。再接下来就就是面试了。面试呢一般分为店面和on site on set就是现场面试店面呃不同的公司不一样,有可能有一轮。
但是最多我听说好像有三轮的,就是一般是1到3轮吧。然后就是on siteonite就是现场面试,一般会就是让你办签证,可以到美国这边来到公司面试,然后onet一般都有5到6轮,就是基本上是早晨到。
然后晚上结束的那一种。中午呢和这个公司的工程师可以共进午餐,了解一下公司的情况,这个整体的气氛,包括这个文化啊等等各方面,然后可以参观一下公司,就是了解一下这个onite面试。
其实店面的通过率相对来说还是比。比较高的。但是onet的通过率,我们我们看起来可能得有30分之1吧,就是大概3%左右。所所以onite的成功率并不是很高,从店面到onite相对还是比较容易的。
但是从onite到下面这个offer其实相对难了很多。啊,那当然一种就是offer,一种就是被拒了,被拒了就相当于目忘,重新再找别的公司再投简历。那么你拿到offer之后,公司会帮你办签证。
这个主要是进入美国的工作签证。那最后是入职,入职一般都是10月1号以后,后面我会讲为什么是这个日期,这个是一个总体的流程。那么从国内可以投的公司的列表,其实主要还是因为欠证问题解决签证。
其实对公司来讲也是一项很大的负担。所以。尽管国外这边呃硅谷啊湾区啊,这边地方的这个公司非常非常多,但是在国内能投的相对少了很多。因为呃有些公司就是他不太愿意负担这个签证的问题。
所以他就想选择本土的这个这些工程师来招聘。这样的话,他的这个风险啊,代价都会小很多。那么所以我还是建议投一些比较大的,而且肯定能解决签证的这些公司,比方说呃我列的这个顺序其实。
网上有流传所谓的FLAG就是flagF就是facebook。这个大家都知道L就是linked inA呢就是amazon。这呢就是google这四个公司,然后下面微软microsoft twitter。
然后这个sstorm eight其实也是一个做游戏的公司。曾经我在link in被他联系过,所以我知道在国内能投它apple苹果不用说了,pocket games是一个做手游的公司。
就是做手机游戏的公司。然后这个tangle tanggo又叫tangleme它是呃国外的就跟whatsapp跟微信很像的这么一个工具啊,这个也在国内招聘。因为我知道有人跟我同事过来的,他也是这个公司的。
然后think这个好像公司全称是把它连起来的,就是一只思考的星星,它的base也就是总部在加拿大,但是在美国也有,因为我也被他联系过。所以我知道这个在国内也能投。但是我建议还是投一些大的。
就比方说FLAG啊,然后这个微软其实是在西雅图,它不在这个硅谷这边,但是硅谷这边也有分布,就是相对小一些twitter啊,所以我觉得前面几个还是比较大的比较靠谱的公司。
所以说从国内可以投的公司还是非常有限的。那其实公司招聘他本身也有很多烦恼。首先就是其实美国本土的每年的毕业生非常非常多,人是挺多的,并不是人不够。但是呢他的平均水平相对低一些。
其实这边的毕业生可能呃我不是说个别个别可能也有就是水平非常高的。但是总体上来讲,水平其实没有国内的人高,所以有些公司才喜欢从国外招人。比方说从中国啊从印度啊招人,因为他们觉得从这些地方招的人。
就是水平比在美国本土招水平要高一些。那对于他们来讲,负担其实就是呃首先就是店面本身就很麻烦。因为你不在美国这边要面试的话,可能跟HR邮件一来一回可能就两三天甚至一星期就过去了。
所以你店面约个时间本身就很困难。这是一方面。另外一方面就是on site,就是我刚才说的所谓的那个现场面试,他要给你解决机票啊,帮帮你解决时宿。尽管只。😊,一两天对他来讲,这个代价还是很大的。
因为如果在美国本土,你来on site就早晨来晚上回去就完了,不需要什么机票啊,帮你订旅馆啊这些事情。所以这个对他来讲也是一个代价。所以他从店面到on site,就是有可能会有2到3轮的这种店面。
他还是要在在摸摸底,不然的话他觉得这个机票啊或者这种时宿的代价,看看值得不值得把你弄过来on site。那么还有一个很重要的问题就是我刚才说的签证,签证其实是每年4月1号抽签。
然后签证生效的时间是10月1号。所以比方说我现在招人的话,我从中国招一个人。那你最早能入职的时间其实已经是明年的10月1号了。所以对于公司来讲,这个周期太长了。所以比方说我急招一个人。
我希望他3个月内就入职的话,这种他从国外他根本就就是没法实现的。所以这个对公司来讲,他这种等待的流程,他也。😊,的一个代价。正因为如此这些原因。
所以他的这个面试的要求其实是相对这个美国本土这种面试要高一些的。因为对于公司来讲,我花同样的钱。我当然希望招这个水平高一点的人。那这个我从中国或者说从印度招人,我花的代价大。
那么我显然希望我招的这个水平要高,所以他面试的要求高。所以这个是其实并不是说这边水平高,而是这边就是想要这么高水平的人,他招不满,所以才考虑从国外招,所以才把这个面试的半儿提高了。
也就是这个面试的要求会增会增加。这个是我大概分析了一下,为什么就是公司从呃所谓的国外,也就是中国和印度招人为什么这么困难,为什么就是面试很容易挂的一个原因之一。其实这是很大的一个原因。
那么我再提一下签证呃,一般就是来美国这种就是从中国啊、印度来美国这种签证叫H oneB,也就是工作签证。它是一种非移民签证,它和雇主相关。这个HMB是雇主雇主给你办的,也就是你自己你说我想办一个。
他不就是根本就不受理大使馆根本不受理这种类别,你只能办就是所谓的B onewo就是business或者说旅游的这种签证。但是这种签证在美国是不允许工作的。所以这个签证的类型。
以及你在美国的活动范围或者说能干什么事情是直接相关的。HB这种是工作签证,并并且是和雇主相关的,所以说一定要有offer才能办。那有效期一般是三年,可以在延长三年。那6年之后怎么办呢?其实呃在这6年里。
一般公司会帮你申请所谓的移民签证,也就是绿卡。那在这个如果到了某一个阶段,这个阶段叫。如果你把这个阶段过了之后,一般2到3年,你把这个阶段过了之后,你的身份就一直有效了。就是即使你没有拿到这个移民签证。
你的HB就永远不会过期了。所以这个H。😊,期的问题一般不用太担心。那流程上就是我刚才说的,每年4月1号,所有,也就是拿到offer的这些人,他们的申请材料会提交到美国的移民局。
那目前移民局的这个签证发放的名额是固定的是65000人。那如果人数大于65000人,他就随机也就是抽签儿,具体怎么抽,没有人知道,反正应该是个计算机程序在抽签。那这个现在也有很多所谓的proposal。
就是请求希望把这个名额扩大。但是这种提案到目前为止还没有就是被采纳或者还没有被接受的迹象,反正明年应该还是65000人。所以这个瓶颈口在这里。最多最多也就65000,这65000人是全世界的人数。
而且包括很多非IT的,就是所有的工作签证嘛。这个所以每年人数非常少。然后而且美国本土毕业的硕士和博士本科除外,就是硕士及以上的学历,他可以有优先抽签的权利,大概他有一个破,就是有个值是15000人。
在这6000的名额里以内,他们这15000人先抽一下,就是先抽出15000人。然后那些没抽中的,就是这种高学历没有没有抽中的,再和普通的这些人再抽一次。所以他们的中签率高。
这也是很多人为什么想在国外读书,然后在国外找工作的原因之一吧。因为他这个中签率高,并且国外还有一种临时身份。如果你毕业之后有一种叫OPT的临时身份,你可以用那个先工作,所以他可以就是在等来年的抽签。
所以他这个身份可以保持很长一段时间,就是在美国很麻烦的一点,就是你的身份一定要保持住。如果你没有。😊,身份你工作是不合法的,那么没有公司敢聘用你。那如果你顺利拿到了名额,就是抽签抽中了。
你在这个65000个星员当中,那么你就要准备面签。如果你面签成功,这个面签一般不会被拒。面签成功的话,你的签证是10月1号生效的,大概生效前一周还是两周,就是9月底你就可以入境美国了。
所以这个周期非常长,一般都是呃比方说我们现在投简历,我们最希望的就是在4月1号之前拿到offer。因为你4月1号就要把这个申请提交上去,你提交晚了,就不会被受理了。
因为4月1号当天如果超过这个65000人,后面他就不处理了。那然后抽签抽中了,在转年的大概56月份,你能知道抽签抽中了还是没抽中,如果抽中了,10月份就可以入职了。所以这个等待的周期。
包括这种对心理的这种呃压力的这种测试其实还是很大的。😊,那面试的总体感觉,其实呃我个人认为面试其实有一定的随机性,很容易失败,而且失败的原因很难找到。有些原因是就是是可以找到的。比方说呃我我英语听不懂。
我这个口语很差。但是有的时候包括我看了一些面经,也是从头到尾感觉都面的不错。但是最后就是句信。所以有些事情很难说。然后还有一点就是店面的感觉和这种face to face。
也就是面对面的面试其实是完全不一样的。因为你面对面的时候,你有些东西讲不清,你说我可以在黑板上给你写一下,我可以在纸上给你画一下。但是店面你没有任何途径,你只能通过语言,面对面你可以有语言可以有表情。
可以有动作,就可以用各方面你去影响这个面试官,但是店面你没有办法,而且又是英语的这种店面,所以很难适应。😊,然后还有一点,其实是基本上不能说全部5年之内吧,可能甚至10年之内,我指的这个是工作经验。
在这些。5年之内的这些,其实无论你是什么级别,他可能侧重的也不一样,但是都需要扣定。我觉得这点可能和国外不一样,可能国外工作个56年之后再面试可能很少面code定。但是这个国外的面试都要面。
无论你是这个就是high level一点s一点的,还是就是比较基础的这种职位都需要写码,那写码一般有两个google自己就用他们自己的google doc。
那一般facebook等其他公司都用colllab edit这是一个在线的online的这种呃文本编辑器,它不是编译器,就是呃只能写代码不能编译的那种。但是他他可能支持一些高量啊,主要可以你在写的同时。
那个面试官那边能看到,这个是面试的一个工具。那。😊,刚才我已经提到了面试肯定都是英语,这个听力啊,包括自己表达,可能要注意一些内容。包括这个如果你赶上面试官是印度人的话,他的英语基本上是很难听懂的。
所以这些都是影响你面试成功的这这种公这种因素。包括有些时候呃,反正我也是遇到过,我在投那个storm就是刚才那个STORM8的那个公司的时候,就是前面都面的不错,最后给我发封邮件。
说对不起我们这个职位close的了,就不招了,那你一点办法都没有。因为公司他什么时候招聘,这个取决于他们总体上的决策,所以影响你面试成功的这种这种呃因素非常非常多,而且非常随机。
所以就是不要试图是说呃我去搞一个题海战术,我把这些题目准备完了,面试肯定没问题了。即使你面试一点问题都没有,最后公司还是可以任何理由拒绝教你。所以这些呃反正我就觉得有点就是随机有有有点碰运气的这种感觉。
😊,当然,实力还是很重要的。如果你足够优秀,呃,反正至少公司要你的概率是很大的,大概就是这个意思。那大体六程我刚才已经说到了,这个再详细说一下,首先HR跟你聊天,注意HR其实并不是要考验你。
因为HR的这个很大一部分收入其实就来自于他给公司提供人才,所以他会想方设法帮你拿到offer,他会给你一些公司的背景,甚至会帮你准备面试,给你一些资料让你读,这一般HR他对你都是非常友好的。
所以你要搞清楚这个关系。HR跟你是朋友,而不是敌人,面试官是呃就是是想从各方面卡你的。但是HR一定是从各方面帮你的,你有什么要求都可以跟HR提,这点要注意。
然后店面刚才说了1到3轮on site一般是5到6轮。😊,可能还包含一轮和这个manager,就是和你的顶头上司聊天。你们互相之间,可能manager感觉你能不能融入这个公司的氛围。
能不融融入这个team。然后你的这个各方面这个文化呀,包括比方说你的体育运动这种喜好啊,各方面吧,就是和公司的氛围是不是match极少情况on会变成店面,反正我当时就是呃我就没有进行过ite。
就是到ite那一轮,人家说你这个办签证太麻烦了,我们改成店面嘛,店面有好也有坏,他的好处在于因为你on site你还是要过来美国一趟,然后要折腾时差呀,因为一般你可能到前一天晚上到这边。
然后第二天就开始面试,其实还是挺累的。但是店面也有不好的地方,就是我刚才说的,你能表达了,你能表现的这种太少了,你只能通过语言你你想画个图什么的,这个很难,所以所以店面有好有坏,因为毕竟看不见人嘛。
我的ite就被改成店面了。😊,我就属于这个所谓的极少情况。那后面还有一些所谓的cultturefetting和bground checking。这个其实问题不大,就是看你能不能融合融入这个公司的气氛。
然后可能找一些推荐人啊,帮你调查一下你的这个背景。这些问题不大。然后有些公司比方说以google为首的这种公司会有一个所谓的team matching。
它的这个面试是general的就是嗯谁都可能给你面试,最后面完之后,我们再决定你去哪个组。当然有些公司是所谓的teamoriented的,就是你在面试之前,我就知道,如果你成功你要去哪个组。
所以公不同的公司大体流程相似。但是具体的细节还是有些差异的那最后当然足够幸运的话,就会给你offer。这个是大体的流程。那面试的准备。其实嗯也是包括这个非技术和技术。那对于非技术来讲。
就有一些比方说你如何做一下自我介绍啊,你做过什么项目啊,然后还有一些行为上的问题。比方说如果你的呃同一个组里面的人不合作的话,你如何协同啊。比方说他很努力,但是它就是做的很慢,影响了你的进度。
你怎么找他说啊,这种这种问题都都可能会问还有一些比较开放的问题。比方说facebook会考你这种啊,你觉得我们现在这个产品有哪些缺陷啊,你觉得应该如何改进啊啊等等,就是这些都是非技术的问题。
然后技术面有的公司会一上来给你一个所谓的only assignmentign,简称就是OA,就是在网上给你一个题,然后一周内比方说三天之内,你抽3个小时还是6个小时或者一个小时等等。
抽一定的时间把这个题做了。你打开那个时间就开始倒计时,然后这个基本上做题目就是online价值的形式,就是写一个完整的程序,包括输入输出有有这个规定好的格式。😊,然后你最后可能还要注意一下程序风格啊。
包括要加一些注释啊,让别人读得懂啊等等。呃,在这个hacker rank平台或者可delete平台,这是两个比较常见的平台。反正我当时面rocky feel的时候就有这个好像是ha rank吧。
在在那个平台上给了我一个题目去做。然后就是店面店面基本上就是编程和算法不会问太难的东西,因为店面相对还是比较痛苦的。然后onite的话可能会问很多别的东西,比方说逻辑题啊,开放问题啊,呃。
系统测试啊呃系统设计啊测试啊,这个stem design是这个很难的一点,就是比方说让你设计一个分布式缓存啊,设计一个哈西啊,你要考虑很多很多问题,这个也是看功底的一个。但是这种也不太好准备。
就是要多读一些资料吧。😊,我大概举几个例子啊,这些题我不会太细的讲,因为呃本次课其实主要还是一个介绍性质的,并不是一个技术上这个讲题的这种性质的啊,比方说一个题100个锁。
就编号1到100开始都是锁着的。第一个人呢把锁全都打开了。第二个人呢把二的倍数的锁再再把它锁上,也就是第I个人每一轮把I的倍数那些锁进行反向。那最后这。😊,I等于1的2一直到100。
最后锁每个锁是什么状态呢?其实每个锁的操作次数取决于这个所的约数的个数。那么哪些数约束个数是奇数个,哪些约数个数是偶数个的。大家可以想一下,其实完全平方数的约约数是奇数个。
非完全平方数的约数是偶数个偶数个约数和奇数个约数对应着不同的状态。这个是呃可以理解为这种智理题或者叫逻辑题吧。那么这个呢。也是一个就是概率相关的。三只蚂蚁在一个三角形的三个顶点上沿着边走,速度相同。
那么碰撞的概率是多少?注意速度相同,如果沿着同样方向走,就是顺时针或者逆时针来讲,那永远装不上。但问题在于你需要枚举,它有多少种方向。所以三角形一共有多少种方向,然后哪些方向会造成啊碰撞哪些不会。
就是我刚才已经说了,全顺和全逆就不会碰撞,否则就会。那如果不是三角形是一个N边形呢?这个可以推出一个公式,也是这个国外面试可能会遇到的这种呃和国内不太一样的这种题目。😊,那么还有这种数学题。
其实这个属于计算几何的这种问题。呃,计算几何嘛,可以理解为我们高中时候学的这种解析几何,就是用数表示图形的这种。比方说给你两条线段判断他们是否相交,线段就给你两个端点嘛。X1X呃Y1和X2Y2。
那如果是直线判断它能不能相交。包括如果相交能不能把这个交点求出来,这些其实没什么难的,就慢慢算就好了。但是如果写代码的话,还是就是稍微有一些复杂的,也不是一下子就能写出来的。😊。
那么第四个问题其实是真正的google面试的题,给你一个举阵。然后呢,比方说我们认为它的上面和左面这个矩阵,我们四条边认为被被海洋包起来,它的上面和左面是大西洋的点,呃,是大西洋下面和右面表示太平洋。
那每个方格有一个整数就代表当前方格的高度,也就是海拔。那我假设每个方格都有水,那水是往低处流的。如果这个方格比它邻居的数要大的话,它就可以流到对应的就是邻居的那个方格。然后问你啊,哪些。
格的水既可以流到大西洋,也可以流到太平洋。其实这就是一个着路的问题。我们可以用BFS或者DFS从大西洋和太平洋分别做一次,看看大西洋能连到哪些点。太平洋能连到哪些点。那能同时被两个海洋连到的点。
就是能同时到两个位置的,呃,到两个海洋的位置,其实这也不是一个难题,只是大概举一个例子,那边是什么?对于图来讲,节点就是矩阵离点边呢就是邻居嘛,邻居,并且它比它邻居高。
也就是水往低处流的这种就一条有效边,所以这个图是我之前讲过的一个隐视图搜索的问题。😊,那还是算法题给定一些日志,这个你可以理解为比方说facebook呀或者这个呃QQ啊等等吧。呃。
就是你有一些登录和不登录的这种状态。比方说我知道你T1到T2T1时刻登录T2下线,那我给你日志全是这种派2的。那么我问你最多同时有多少人在线。当然还还还可能问其他的问题。
比方说让你把这个从T1到T2多少人,从T2到T3多少人,这种就是以某种格式输出啊,这个题目可以出的很复杂。但本质是什么?我们把这个时间拆开,上线就加移,下线就减一。
然后把这个按照这个第一维按照时间这维排下序,然后记一下数就可以了。😊,我们就是不断加1减1加1减1,找当前的最大值,就是在线人数最多的那这个关键就是把TT2这种拆成T1和T2这种。呃。
T1正一和T2负一的这种形式。所以这个也是经常遇到的题目。那还有这个其实在li code上好像也放了这个题,就是。给你A到B之间的整数,然后让你做安慰语,安慰语就是呃两个都是一才是一,否则就是0嘛。
那我让你从AandA加1and A加2一直end到B,注意A是小于等于B的。问最后结果,当然一个一个and肯定不可以,我这AB可能就是中间差的很大。比方说A是一B是10的9次方。
你总不能循环十的9次方次嘛。关键是你考虑一下什么时候能产生零,什么时候产生一1。1点算,这个是安慰语。我曾经出过一个安慰一或的意思也是一样的。😊,那剩还有一大类就是系统设计,这种其实非常非常难。
而且也很难准备。这个比较考功底。如果有一些工程经验的话,嗯,面这种问题会会好一些。比方说如何设计这个微博中的短链接,我给你一些URL你怎么呃在微博里面它会把它变成那种短链接有呃twitter也是一样的。
就是呃就不是把原始的URL弄出来,它会编码一下,那么这种编码,我们对于同一个URL编码一定要是一样的。那我们如何做哈希呢,如何去重呢?包括这个短链接,有可能服务器在不同的机器上,单机和多机做法也不一样。
那我们如何做这个编码呢?就是怎么把它真的变短了呢?等等,各方面有很多问题需要考虑。😊,那还有很多系统设计题,这些都是曾经见到过的。最后一个其实相对简单一点。因为和算法还相关一点。
比方说怎么设计一个在线售票系统,同样有单机多机的问题。然后包括如果多机一台机器挂了,然后你怎么办?然后数据肯定要涉及到这个数据的这种备份,因为机器可能都可能挂掉。那备份它就有一个呃一致性的问题。
你可能有一个upate有一个更新之后,你在A机器上更新了,在B机器上没有更新。那么你怎么处理这种冲突,各方面都需要考虑。然后这个如何设计一个文本编辑器类似的。但然这个可能没有多机的问题。
但是也有可能类似于考这种呃google doc的这种设计,因为google do可以同时编辑。那如果操作有冲突怎么样?那你后台是以什么结构来存的,都可能考,包括设计一个电梯系统。
比方说这个电梯系统里有三个电梯,那么来一个请求,你让哪个电梯去去接受,有一个呃什么样的算法来调度这个电梯。😊,其实还是很难的那在线地图这个在就是LBS的这种。
比方说facebook呀这种就是你怎么表示一个点,怎么表示它周围的兴趣点,怎么跟好友共享位置,怎么广是广播还是这个独立的算,怎么提高这个缓存,怎么提高性能,反正有很多问题要考虑。
包括facebook那个所谓的newsfe的,你的好友有update之后,你怎么知道是他推送给你,还是你主动拉过来,你什么样的方式,呃,对于比方说好友多的,或者你这个。😊,你关注人多的和呃怎么说。
你粉丝多的和关注多。当然facebook边是双向的那微博的话就是对于你粉丝多的和呃这个关注多的,你是不是都用同样的策略来考虑,怎么设置这种阈值,有很多问题要考虑啊,包括多机爬虫。
其实这个和那个短链接那个问题有点像同样涉及到分布式机器啊,如何哈西啊,如何去重同一个URL这个如何不被爬两次,到底是广东优先还是深度优先如何存储,都有很多问题。那这个也是现实中真的被考过的。
用一个类表示窗口,那么给你一个鼠标的点击的位置,如何判断它在哪个窗口上,然后二叉数的序列化与反序列化。所谓序列化,就是你用一个字符串也好,用一个二进制编码也好,把这个二叉数存下来,比方说把它存到文件里。
反序列化就是你读这个你刚才存好的那个文件,把这个二叉数恢复出来。这个都是很现实的问题。😊,那还有一些开放问题,比方说如何测试一支钢笔。比方说你甩一下,看看它漏不漏水啊,这个呃这个尖是不是太尖滑纸。
是不是不太监,反正各方面都会考。然后包括如何向老奶奶介绍数据库是什么东西,看你能不能用通俗的语言来表达你的想法。然后有一些google很喜欢考的这种很现实的问题,你估算一下某个地区的人口数。
然后这个地区建多少个加油站,或者说建多少个餐馆合适,你去调查一下这个这个地区要不要建在某些地方建一个公交车站,经常会考这种问题。然后呃facebook喜欢考这种。
比方说给你一些地区他说呃这些只有这些地区的用户说我们访问facebook特别慢,其他地区没有这个问题,你怎么测试,到底是呃就是你这个地区的服务器出了问题呢?还是呃就是他们那边网速的问题,还是怎么着。
你怎么把这个问题发现,怎么解决。啊google曾经考过类似这种给给定一个网站,就是告诉你这个网站访问速度特别慢。网站。😊,大家都知道它的服务器有啊web服务器和数据库服务器。那我问你到底是哪个服务器慢。
你如何检查,如何证明你的观点啊,这种问题相对就开放一点,看看你个人的这个观念会怎么样。然后第十类其实刚才也提到了,就是所谓的行为问题,英文叫behavior嘛,就是看你个人的做事风格。啊。
刚才已经说到了,对现有的产品你有什么建议,如何改进,你想做一个什么新的功能。那你还可以说我如何我是你的主管。那么你跟我说我想做一个新的功能,我不太同意你怎么说服我说这个功能非常有必要。
那假设我现在同意你做这个功能。那你如何证明你这个功能最后做出来是成功的,或者说如何证明你做出来这个是失败的,你怎么分析数据呃,就表示你最后做成功了或者做失败了。
这个这三个其实都是facebook真正被问到的问题。那还有一些就是比方说有有个团队呃,刚才已经提到了某些人效率非常低啊,或者说某些人不太合作,你怎么办?你要不要向主管汇报,你不汇报的话,你如何跟他沟通。
你言语上你的风格上的都会体现出来。😊,那,刚才已经提到了很多,其实最后做一下总结吧。首先就是面试很容易失败。其实我个人面试也是失败了很多次,当时就是心情啊,各方面都都低落到了极点吧,就是人都快崩溃了。
所以说不要灰心,要把这个面试当成锻炼,要积累经验。其实这些都是说说容易,真的亲身经历了一次就是面一次挂一次那种状态,其实真的感觉很差。然后。😊,这个签证需要抽签,今年已经有23点,不知道多少。
就是23万人以上了。注意我们只要65000人,所以就是大概3分之1的样子吧,3分之1强一点的样子可以中签。但是这个没有任何公司有办法。因为这个是美国政府的决策。所以公司即使他非常非常想要你。呃。
如果你签证没抽中,那也没有办法。那一般情况有的公司就会让你在国内等一年,第二年再抽,再筹不中,那再想办法。那这都还属于比较不错的公司。有的小公司他可能不愿意再等了,很有可能把你offer收回。所以。
这种就是说还是要一定的心理承受能力吧,有可能费了很大的力量,最后面试也成功了,也拿到offer了。然后签证没有抽中,然后公司收回了,确实有这种情况,我也听说过,所以各方面都是要呃要怎么说吧。
要运气和实力并重吧。然后比较好的公司这个其实我知道的,目前最好的还是google吧。他可以安排你去别的国家先待待一年,然后第二年再抽,或者因为如果你在别的国家再过来的话,还有别的这种类型的签证,叫L。
就是所谓的transfer的这种签证。呃,google的这个这种让你去别的国家的选择也很多,我知道的有人去了英国,伦敦,有了有人去加拿大温哥华啊,各方面都各各个国家都有吧。😊。
然后还是要奉劝大家一句所谓的实力加运气才等于成功。这个确实是呃面试本身不光是靠实力,也要靠运气,然后签证,那就是纯属运气,一点办法都没有。所以这个也是我今天想跟大家分享的一点心得和感触吧。好。
今天的课程就到这里,欢迎大家给我提出批评指正。谢谢大家。😊。
人工智能—面试求职公开课(七月在线出品) - P6:概率面试题精讲 - 七月在线-julyedu - BV1Xf4y1r74s
欢迎观看7月算法公开课。我们本堂课的主要内容是概率相关面试题精讲。我将从如下几个方面讲述本课,先讲一下简介,然后讲一些题外话。接着讲一下概率相关的面试题的总体分析。然后讲7个例题,最后总结结束本课。
关于简介概率。主要在面试和笔试里面考察的是如下几个范围。对独立事件的理解,古典概率也就是。计数做除法。这个计数主要包括排列组合方面的这种数数,然后分子分母数出来做一下除法。还有一个是条件概率。
给定一个事件成立,求另外一个事件的概率。关于期望的计算,然后是随机数的产生和利用,这个比较重要,主要是采样采样主的是指指的是利用,然后产生这个打的星号比较重要,前四个呢主要出现在笔试中。
因为有很多的填空啊选择啊计算题,最后一个可能出现在笔试的大题里面。当然还是更常见的是面试中出现。说一些题外话,首先就是随接数的产生并不容易。一个著名的计算机科学家。
在他的著作bearcomp programming中,其实用了一本书的这个篇幅,提到了如何产生随机数。我们只要有一个感性认识就可以了。其实随机性和不可预测性还是有一定差异的。
这个差异在密码学里面体现的尤为明显。比方说我们固定一个数M这是一个整数,对所有的自然数N它对M取域数显然是均匀的。因为只有0到M减一的这些情况,每M个自然数就有一个周期,所以对于所有来讲。
它显然是一个均匀的。并且呢它其实是有一定的随机性的。因为N如果随机的话,它这样除完了也是。😊,有一定随机性,我们可以用它作为随机函数,但是在密码学里面通常不采用它,因为它是可以预测的。
我们可以用0123这样放出来,它最后发现它是周期的。所以所以密码学一般不用这种东西作为随机函数,它和我们理解的随机还不太一样。那如果面试题里面考察我们。有。构造一个随机数发生器的话。
一般都会告诉我们有一个随机数发生器存在,它不可能让我们凭空构造。因为构造随机数并不容易。关于期望的计算一般转化为方程组。这个A1A2是A的邻居加一,这个是概率,其实就是跟那个图论的那个邻居很像。
看差一步之前它是什么样子,或者说一步之后它是什么样子。对于A一来讲,也有类似的式子。所以最后我们会形成一个N元一次的方程组可以把每一种情况的期望都算出来。这个是计算期望的一般方法,这是一些题题外话。
我们来看具体的例题。先做一下总体分析。对于概率来讲。一般考的不会太难,简单。因为概率论本身非常深刻,有很多微积分啊,高等数学的东西存在,但是一般面试笔试都不会考,对于笔试来讲,会考概率和期望的计算。
对于面试来讲,一般会考随机数产生和利用,利用就是采样。当然,随机数产生也可能在笔试的大题里面考。至于算法,我们最常见的比较熟悉的就是快排面试可能会被问到,这里面有一定的随机性。
因为我们在partition的时候,选取的那个分区元素是随机选取的,避免了最差情况的频繁出现,达到了一个期望的Nlog n的时间复杂度。具体的题。第一个题其实主要帮大家理解一下这个独立的概念。
其实它并不能算作一个真正意义上的题目。我们看一下我们通常理解的独立是说两个随机变量没什么关系,就是独立。我们来看一下,假设X1X2是两个2元的随机变量。什么叫二元随机变量呢?就是。要么是零,要么是一。
各占50%,只有这两种取值就是二进制的一个beat,或者说一个位。那么X3呢,我们是X1异或X2,这个是一个定义,我们把它定义为这个东西,易或呢就是两个二进制数相同取零,不同取一。
那看起来X3和X1是有关系的,和X2也有关系,都有这个等式存在嘛。但实际上,X3和X1以及X2都是独立的。😊,很简单,我们可以枚举一下X1X2所有情况就4种嘛。
00对应的X3是001X3是110X3也是11对应X3是0。可见呢当X1等于0或者等于一的时候。X3其实各有一半的情况等于0或者等于1。你看第一位和第三位,它等于0,它等于0,它等于0,它等于1。
这个第一位是一的时候,X3也可以等于0和1。所以呢。X3其实和这两个东西是独立的,尽管有这个等式存在。看起来有点反直觉,因为有的等式应该不独立,但实际上是独立的。所以我说关于独立,不能凭感觉,不能感性。
我们需要根据定义来考察,其实独立的定义很简单,A和B是独立的。如果A和B同时发生的概率等于分别发生的概率的乘积,大家可以带进去验证一下,就知道他们是独立。我们来看第二个例体。这个也是比较重要的。
经常出现的例题,构造随机数发生器。给定一个随机数发生器rend7,刚才我说了,一般都会给一个让你构造一个它呢均匀产生1到7之间的随机整数,也就是每一个概率是7分之1。
我构造run10均匀产生1到10间之间的随机整数,怎么构造呢?😊,这种问题其实七也好,十0也好,经常有这种问题给了不同的整数,让我们构造。关键问题在于。我们不想要的可以扔,但是要保证等概率。
我们在目前等概率的情况下,我们把不想要的情况出现。把不想要的出现的情况都扔掉,然后再继续再做后面的工作。每一步我们都可以fit掉,或者说过滤掉一些不想要的情况。但前提是要保证等概率。
我们先看一个比较笨的办法,1到7之间有4个基数,3个偶数。13574个奇数,2463个偶数。我们呢可以扔掉一个基数,我们调一次ra7。如果是7的话。我们就继续掉,不断的调,直到它出现1到6。
为什么要这样呢?因为我们要保证正好有三个奇数和三个偶数。那么这个时候呢,我们把奇数看成一偶数看成零的话,实际上我们已经构造出来一个均匀产生零和一的随接数发生器了。那么。其实有了01就有了一切。
因为有了二进制嘛。所以呢我们产生4个这样的01。这样就构造出来0到15之间的整数,因为正好是2的4次方,0到15之间的整数,并且这些也是等概率的。因为每一个be是零是一的概率都是2分之1。
那么我们把不想要的扔掉,把保留1到10就可以了,把零扔了,把11到15也扔了。所以我们扔了很多东西,最开始把7全扔了。后面又把零和11到15都扔了。所以我说它比较笨,我们看一个它的代码。😊。
注意这里面这个代码实际上是不能运行的。我们假设rund器存在,实际上它不存在嘛。如果是7,我们就一直产生。当它退出的时候,就是不是7了嘛,就是1到6三个奇数,三个偶数。
我们取得的第一位实际上就是对二取的余数,这样奇数就是一偶数就是0。所以这个就产生了一个01,并且是均匀产生的。那么我们如何构造刚才说的1到10呢?😊,循环4次产生4个这样的东西,把它接起来。
这个就产生了一个刚才我说的二进制的数0到15。那0到15,我们把零扔了,15111到15都扔了,所以这也是一个循环。直到它正好是1到10,我们能保证等概率。
这个是它的代码,我们看一个聪明一点的办法,刚才说了,用的是二进制,它本身是1到7,我们为什么不能用7进制?这个每一个产生的概率都是7分之1,所所以我们没有必要扔嘛。那么我们把它减去一变成0到6,那么。
跟刚才二进制的道理一样,我们产生两位七进制数,因为两位就够了,产生的数是0到48,并且是均匀产生的。每一个概率都是49分之1。啊。显然,我们可以按照刚才的策略,把所有不想要的都扔了,只要1到10。
我们有一个更聪明一点的办法,我们只扔40到48,为什么扔它呢?因为这个9个数是比较独立的,剩下的都是啊0到910到19、20到29、30到39,这个0就是个位上0到9,这些出现的次数都一样,都是4次。
😊,所以我们把40到48扔了,这样的话产个位上产生零,产生一产生一直产生到9的概率是一样的。我们把0到9对应于我们想要的1到10。所以关键看我们扔掉之后,要也要保证概率相等,才能随便扔。
所以这个代码也非常简单,七进制嘛,这是七进制的高位乘以77进制低一位。刚才说了40到48扔掉,如果它大于等于40,我们就扔这样产生的最后退出来了,实际上产生的是0到39。
0到39里面每一个个位数都出现了4次。所以他们也是等概率的。我们把它取个位加1,对应我们想要的1到10,这就可以了。😊,为什么说他聪明呢?他扔的数少一点,我们只扔了40到48这种数不像刚才扔了很多数。
😊,我们看一下关键问题,要保证均匀才能扔掉。比方说我大概举个例子,假设我有一个random2,ran2呢产生是要么是一,要么是2嘛,这两个东西相加减一,显然范围在1到3里面。
但是注意它们产生1到3并不是等概率的,大家可以每举算一下,1212每举算一下,产生一和3都是4分之1,而产生2是2分之1。所以他们不是等概率,我们并不能随便扔,要扔之前要保证等概率,这个是一个关键问题。
要保证均匀才能扔掉。另外一个想说的是,其实一个实验,假设我们有一个实验,它做一次实验成功的概率是P不成功的概率是一减P。当然这里面P大于零小于一P等于零或者等于一就没什么意义了。😊。
我们不断的做这样的实验,直到一次成功,就是如果失败,我们就再做一次失败,再做一次,直到成功。那么到成功的时候,期望做了多少次实验呢?它是P分之1。😊,啊,举个例子,假设我们有一枚硬币,它是均匀的。
要么正面,要么反面我们就不断的扔。如果是反面,我们就继续扔。直到扔到一个正面,我们期望扔了多少次呢?其实期望两次就够了。那怎么算?其实非常简单,就用期望的定义。假设X是期望。那左边怎么说?😊,Pear。
一次我就成功了,就是第一次成功。第一次失败的时候就是一减P后面是跟那个第一次相同的情况。原来期望是X的话,现在肯定要X加一,因为多了,第一次这是一个等式,用X自身表示了X。
那么这个东西解出来就是X等于P分之1。😊,那讲这个有什么用呢?我们可以把它作为一个结论。我们可以分析一下刚才讲的那个笨方法方法一以及聪明一点的方方法。2、他的期望循环的次数。因为我们扔了很多数嘛。
最后成功的时候,我们期望循环了多少次呢?这个是我算到的结果。有兴趣的同学可以算一下。😊,明显这个比就是方法二比方法一要期望上要少循环很多次。这个是我想说的一个重点。那么继续看第三个题。
就是用不均匀的构造均匀的。刚才说了,让你构造随机数发生器,一定要给你一个,不然你没法构造。那么现在给你一个,它是不均匀的。它以P的概率产生0,以一减P的概率产生一。
这里面P还是大于零小一的等于零以及等于一都没太大意义。那么构造一个均匀的,产生零一的随机数发生器,它是算法导论的一个习题,看起来好像无从下手。但实际上我们用它产生两次,产第一次产生零。
第二次产生一的概率和第一次产生一,第二次产生零的概率其实是一样的,都是P乘1减P。😊,那么有这个一样就好办了。我们把两次产生相等的全扔掉,直到出现,要么出现01,要么出现10,我们才留下来。
就是这样产生两次相等就继续相等就继续。直到他们俩不相等,不相等,要么就是01,要么就是10。根据我们之前说的,它们概率是一样的。那么我们就返回第一个数,其实返回第二个也可以。
我们相当于用01代表了最终的0,用10代表了最终的1。所以这样的话我们就以相等的概率返回0和返回01。有兴趣的可以算一下这个东西成功之前,我们期望的循环次数有多少次,这个是我要讲的第三个题。😊。
看第四个题。这个确实出现在某个公司的笔试题里面。它是一个选择题,让我们算就是给定随机变量XY分别均匀的在0到A这个区间以及0到B这个区间里面分布。当然,比试的时候,A和B是一个给定的数,A给定了一个数。
比方说2啊,B给了一个三,大概是这种。那再给一个数,Z,这个也是个给定的数,问你X加Y小于等于Z的概率。这个题难就难在,它是一个实数,它是一个均匀分布的实数。所以它里面有无穷多个数。
我们不能如果是整数就好办了。我们可以直接枚举出来。那其实我们可以把它转换为面积。如果这个横坐标这个是A竖的是B的话,其实这个XY的所有可能性,其实对应于这个矩形的面积。那么X加Y呢,X加Y等于Z。
我们可以画直线,当然画两条这个Z的不同矩值,对应了不同的直线,那么这个概率对应于什么?对应于这个矩形。😊,在直线下的面积占这个矩形面积的百分比。比方说这条直线就是三角形除以这个矩形面积。
那么这条直线呢其实就是。这个不规则的图形除以这个矩形面积,当然可以用矩形面积减去三角形除以这个。矩形面积,所以它就变成了这么一个问题。我们带进实际数的话,算这个很方便。我后来还出了一个题目。
就是键盘输入这种AB和Z,然后算一下需要一些分类讨论,考虑这个直线在哪儿。如果在这的话是这样的。如果在对角线上方的话,是不规则的。如果彻底在矩形外面的话,实际上就是百分之百就是一了。所以这个是。
相当于是连续的随机变量的和,大概算这个东西,这个也是实际中的一个笔试题。我们继续看。这个是我今天想讲的一个重点,采样问题。😊,这是水库采样,这个名词起源于也是可诺斯的著作。那。
我们假设有若干个对象是留进来的,什么叫留进来的?我们可以把它想象成列表,而且是一次性的留完就完了。所以我们不能或者说我们的空间不允许我们把它们全保存下来。
我们可以想象我们只有1个API就是get next的,我们只能在当前得到下一个,得到下一个,我没有办法一上来把所有东西都存下来。当然你说我把下一个下一个下一个都存下来也是可以的。但是假设我有上亿个元素。
我让你取,比方说只取100个,我没有必要把上一个都存下来。问随机取K个,当然可小于总数,一般还是远小于问有什么好的算法。😊,那这个算法非常简单,我们用一个数组A保存K个数,这个数组A。
最后就是我们要的那K个元素。当然下标0到K减1,这里面假设下标从零开始,那对于第I个元素,那我们不断的ge nextex,我当然知道它是第几个元素了。当然这里面I是从一开始的。
如果I小于等于K什么意思呢?就是我现在还没有存够K个元素,那有一个要一个我们就把它存下来。当然这个下标正好差一嘛,所以我们把这个第一个到第K个元素都已经存下来了。那对于DK加一个元素以后,我们怎么办呢?
关键在这儿我们可以换掉之前的元素。😊,对于I大于K,我们产生一个随机数。这个有两种说法。第一种就是我产生一个零到I减一的之间的随机数,或者叫呃一到I之间,这都一样偏移了一下。
那还有一种说法是我随便产生一个均匀的随机数,然后对它对I取余数,这个根据我刚才讲的,如果这个是均匀的话,它对I取余数一定在零到I减一之间均匀分布。所以这两种说法其实是一样的。
其实就是产生一个随机数是零到I减一之间均匀分布的。那么既然它是零到I减一之间,它有可能小于K。因为I比K大嘛,它有可能小于K,也有可能大于等于K,如果小于K我就存下来,存在哪呢?存在AX这个位置。
X就是这个余数。所以尽管我最开始先把K的元素保存下来。后面还有可能把它踢出去。因为这个数组是会被覆盖的,我用AX来存放新的元素的时候,旧的AX就被扔掉了,所以这是扔掉之间的元素。所以开始K的存下来。
只是暂时的并不稳定。它被替换了,后面还有可能不断。😊,能可给替换?那这个算法非常简单,其实就这么两步。那我们来看一下,大概算一下它为什么是对的。首先说一下这个算法的优点。我们不需要知道元素的个数。
因为我们是第I个元素过来之后,我们直接决定产生一个随机数,决定要它还是不要它的。所以。😊,我们不需要预先知道元素的个数。那么。关键是证明。假设目前已经流入了N大于K度元素。
我们先看一下对于第I个元素是怎么样的。第I个元素被选中的可能性。这个I小于等于K的时候。显然,I小于等于K的时候,最开始我们是要它的,它的概率是一,关键是它后面有没有可能被换掉。
它只有在第K加个一个元素,以及往后的元素才可能被换掉。那么被换掉的概率是多少呢?第K加一个元素如果换掉它首先它产生的随机数有K加一种,因为是对K加一取模的嘛,取膜的话,随机数有零到K。
正好也是K加一种情况,只有它模等于这个I的时候,我才会把它换掉。所以只有一种情况,我才会把第I个元素换掉,所以有这么K加一分之K这个情况不会把第I换掉。后面也一样。每每一个都只有一种情况。
会把DI个换掉。那么全都不换掉,它的可能性就是都只差一。那么这个式子其实可以相消前一项的分母和后一项的分子都能消掉。那么最后就剩下这个N和这个K了,所以。😊,对于I小于等于K的话。
它最后保留在我们想要的那那些元素里面的概率实际上是N分之K。那么对于I大于K其实是类似的。刚才说了。我什么情况下才能要这个元素呢?就是。😡,对第I个元素,它产生的随机数要小于K,也就是0到K减1。
所以我保留第I个元素的,就是在第I个元素过来的时候,我保留它的概率是I分之K。那么后面不被换掉也是一样的。I加一除以I都是正好差一嘛,只有一种情况会把它换掉。所以这个跟刚才是类似的。
算出来也是N分之K都向掉之后只有第一项和最后最后一项。所以。😊,无论是I小于等于K也好,I大于K也好,我证明了对于任意一个元素,它最后保留下来的概率是N分之K。那么显然我们总体上取K个元素嘛。
所以这个证明了每一个元素在我们最后那个集合里面的概率是相等的。所以它等概率的保留了每一个元素,这个就讲完了,它是一个很重要的抽样的方法,后面有一些应用。我们来大概看一下。
有些扩展K等于一的时候是非常特殊的,其实可以类似做。大家可以看一下,把K改改成一之后,这个算法是怎么样的。那么对应的面试题其实有很多,有一个若干行的大文件,我要随机选择一行,其实就是K等于一的时候。
我们一行一行读进来,产生随机数,决定是要它扔它就可以了。另外也是一样的,有一个不知道长度的列表,随机选择一个或者多个元素,其实也是选K个元素一样的。我们知道便利链表的时候,我们知道它是第几个元素。
按照我刚才说的方法做一下就可以了。😊,我想讲了一个题,在例七里面会讲,就是带全采样。就是如果刚才我说的那个采样是我最后要保证每个元素出现的概率是一样的。如果我采样,我就要求随机选一个元素。
并且每个元素有一定的权重,权重大的,我最后选择的可能性大,该怎么做。一会可以看一下例7。你先看一下例6。😊,第六是我想简单讲一下的,就是所谓的random shuffle。😊,什么叫randomsh?
在STL里面,C加加的STL里面有这么一个函数,可以把一个数组打乱,它其实是均匀产生0到N减1的这么一个全排列的一个其中的一个排列。😊,那方法一就不用说了,我们可以随机产生一个一到N的阶成之间的随机数。
因为已经假设有一个随机数发生器了嘛。😊,那么。这个1到N的阶成正好对应一个排列,每一个数对应于第几个排列。当然这种面试答这个肯定不符合要求。你因为你根本什么都没做。当然你能把这个数转化成一个排列。
这个也是li code上一个问题。关键我说这个常规方法,请大家思考证明,这个也是算法导论上给出来的经典算法。😊,循环I把I和啊首先要付下初值AI等于I就是A0等于0AN减1等于N减1就负下来。
然后把AI和I到N减一交换。注意AI可能和AI本身交换,我这标红了,并不是把AI和I加一到N减一交换,所以它有可能是不换的。😊,大家可以证一下它这个最后每个排列产生的可能性相等的代码就是这样。
关键是这里。把AI和I到N减一交换,这个是对N减I取余数,加上I,恰好是I到N减1之间。所以这个也是非常简单的一个问题,这个也是random shuffle的后台的实现,也是这样实现的。
关键在于他的证明留做思考题吧。看。第七是我想重点讲的,这个在我们的社区里面也有人问到过一个呃音乐的推荐问题。我这里面把它抽象出来了,就是给定N个元素,再给N个全值。我们按照全值的比例抽样一个元素。
什么叫按照全值的比例?比方说一个是三,一个是5,就两个元素。那么我最后。选择这个三的概率可能只有呃8分3%,选择5的概率只有85%。也就是说他们最后要成比例的选五的可能性大三的可能性小。那为了方便。
我们这里面假设全值都是整数。方反一。我们按照前置复制若干份就可以了。比方说3个A2个B6个C,我们就这样把它真正的复制3个A2个B6个C,然后把它们看作不同的。然后你不是要一个元素嘛?
我就按照那个刚才第五面讲的那个水库采样的方法弄一遍。😊,找出一个元素就可以了。这个显然因为它们本身是等概率的,然后我把它复制这么多份儿,正好和它的全值的那个比例是一样的那优点其实不用说了。
我们可以用已有的方法解决了问题缺点。😊,假设这边这个权职很大,有好几万,我们其实就三个元素,有1万个C,那我也要复制1万个,这个比较麻烦,但是不失为一种方法作为面试的一个思路吧。😊,方法2。我们产生。
还是刚才那例子,三个A2个B6个C,我们这样3个A对应0到2,正好是呃三个数,2个B3到42个数,6个C5到16个数。那么。整个区间就是0到10。一共11个数,这边也11个东西。
那么我产生一个0到10之间的随机数,看它落在哪儿,落在哪儿,我就对应哪个数。当然判断落在哪儿啊,这个数上我们可以直接循环。如果数很多的话,我们可以二分,因为它这个东西是单调递增的。
我们可以把这个数二分查找它在哪个区间,然后对应出那个元素来。那优点显然是省空间,我们只只产生了这个区间的端点就可以。我没有真正的复制这么多个元素,那缺点是需要二分查找,这个也也是一个显然的缺点。
那我们看第三种方法。😊,我们假设有M种元素,我们先按M分之1的概率随机选择一种元素。这个很容易就随机产生一个数,那个0到M减1或者1到M都无所谓,反正随均匀产生M种元素的其中一个。我们先选择。
比方说这里面我们先选择我最后想产生A还是先产生B,还想产成C。第一步,选择完之后,我们不是选择完就完了。后面我们要看真的能不能产生它。😊,我打了星号,第二步是重点,我们再产生一个随机数。
根据这个权值来判断我们能不能要它。如果要它就要了,不要的话,即重新。再重新产生一个数。那关键我们看一下第二步是怎么做的。这里面说根据全职说的比较虚嘛,比较抽象。我们看一下具体是怎么做的。
怎么个根据全职方法。我们详细分析。怎么做?第二步?其实我们可以这样做,我写了两种情况,这两种方法实际上都可以的。我们。Wtoal表示所有的全值总和。Wm表示最大的全值总和呃,最大的权值没有总和。
最大的全值,这个是所有的全值总和WI就是DI种元素的那个全值。那这个一除是个小于一的,我们可以以这个概率或者以这个概率来选,什么意思呢?我们可以产生呃换句话说。
比方说我产生一个呃0到分母减一这么大的随机数,或者说我产生一个随机数对分母取余数。然后取完余数之后,如果小于分子的话,我就认为是成功。大于分子的话,我就认为是失败。
所以我就相当于以这个概率决定我要还是不要。关键是这个概率为什么。😊,可以用,我们看一下。实验一次成功的概率,什么意思?就是。😊,如果我第一次选择了M分之1,我刚才说了,M分之1选择了一个元素。
第二次按照这个概率。取一下取一个随机数,发现小于比方说我取这个取一个随机数,对分母取一数,发现小于WI表示我能取,那么它就成功了。那么它成功的概率是多少呢?是M分之1乘以所有的每个PI的总和。
为什么是总和呢?因为每个M分之1都可以对应于选一组元素。那么失败第一次失败的概率其实就是一减一下,它就是失败的概率。那么我们看一下最终选择第I个的概率是多少呢?😊。
最终选择第二个概率是一个无穷递错的等比数列,为什么呢?第一次成功的概率,这个就是选择PI第一次成功。那么如果它失败,就是Plu,我们不用管Plu等于多少,反正它是一个常量。那么它失败之后。
我们再选择PI还是这个东西。那么如果他这时候再失败呢,再失败就变成了P6的平方。那么我们再选择PI还是这个概率。所以。它是一个呃每这个后一项和前一项之间的公比,就是P lose。
所我们不用careP lose等于多少,也不用carePI等于多少,反正它是一个无穷第色等比数列。当然可以用公式把这个写出来,这是无穷多项。那么。这个结果显然正比于PI。因为。我们乘的就是PI嘛。
PI可没有平方,这平方都在P6这。所以这个最终我们证明了选择BI的元素的概率正比于PI正正比于PI其实就是正比于WI正比于我们那个全值。所以这个就是我们想要的。那么刚才其实我已经提到了。
我们如何以PI的概率选择那个。元素呢,就是第二步,我们具体怎么做呢?假设PI是A比B具体A和B有可能是这个也有可能是这个。那么我们怎么做呢?才能保证我们以PI的概率选择那个数呢?刚才我已经说了。
其实老办法,我们产生随机数对B取余数,如果小于A,我们就要这是一种说法,还有一种说法,其实和它是等价的。我们产生一到B之间的随机数,注意这是一到B,其实这个是零到B减1,就是这种情况。然后我们看一下。
如果小于等于A,注意这个我标红了,小于等于A,我就要了。那这个呢也是零到B减一之间的数,如果小于A,我就要所以这几种实际上是同一个说法,反正就是产生随机数,对B取余数,如果小于A。
我就要如果给定一个PI,我们可以用这种办法按照这个概率决定要不要这个元素。那么我们看一下刚才讲的那个期望次数。😊,刚才说了,期望次数是成功的次数,成功的概率的倒数。那么成功的概率这已经说是这个东西。
那么其实就是M除以s格PI注意这个分母不一定是一这个这个概率不是之前讲的那个和为一的那种概率。我们看一下,如果我们把PI取的这个的话,那么这期望次数恰好是M,为什么呢?
因为呃所有的PI的总和正好是WtoWtoal和Wto一除就是一了,消掉了。那么如果我们把PI取成这个,刚才我说了PI取这两种情况,取哪个都可以。如果我们取成这个其实还会少一些。😊。
它是这个东西除以sigmaW,注意这个东西比sigmaW要大。所以这个东西这个分分子和分母除完了是小于一的。所以这个总总的期望次数还是小于M的。所以选这个会导致我们循环次数,至少期望的循环次数会小一些。
当然选这个也是可以做的。那么它的应用其实也是这个社区里面的一个问题。我们按照已有的分数,这W其实是分数给用户推荐一些歌曲啊,推荐一些产品。想按照分数一定的概率推荐他想要的东西,这个是一个重点的应用。😊。
那今天的题目基本讲完了,我们再做一下总结。首先是采样,刚才讲了主要的还是水库采样,包括最后一个问题,复制那么多份儿,如何算次数等等。那概率涉及到算法,今天时间关系没有机会讲,但是大概提一下快排的。
刚才说了,分区元素的选择是为了避免最差情况。算法导论在讲随机算法的时候,或者说概率算法的时候,有这么一章讲了在线雇佣问题。它呢。😊,之所以用随机是不想假设输入的分布,因为我们输入有可能很极端。
如果我们考虑问题跟输入顺序关系不大的话,我们可以对输入做一下randomrandom之后,我们这个分布就基本上可以理解为均匀的了,所以这是对输入的一种处理,其实快速排序也是这样。
我们最后反正排好顺序具体输入什么样的,其实关系不大,所以我们用一个这个随机的算法来做。虽然最后输出并不是随机的。那么还有一个重点,因为就是哈奇函数,哈奇函数经常这个对某个数取余数啊等等。😊。
包括一致性哈希,就尽量避免冲突。这个用到了该理论的一些知识。我这个摩取多少的话,才能不冲突,或者说少冲突。概率算法还有一个重点应用,就是所谓的多次尝试。什么意思呢?假设我有一个算法。
每次只有一半的可能性得到最优解,或者说得到正确解。那么如果我能保存这些解,不断的取最优的话,比方说我尝试30次。那么如果30次全失败了,全没得到自由解或者说正确解的可能性只有二的30次方分之1。
2的30次方很小,大概十0的9次方。也就是只有10亿分之1的可能性不得到自由解。所以我们基本上可以认为。😊,它基本上会得到最优结论。所以这个概率算法一个很大的应用,就是我可能先得到一个比较差的算法。
比方说这个有一半的可能性,对这个跟翻应币没什么区别嘛,有一半的可能性对,只有呃很弱。但是我们做30次的话,其实能得到一个很强的算法,这个是概率算法,在实际中的应用。😊,好,今天的课程就到这里。
欢迎大家给我提出批评指正。😊。
人工智能—面试求职公开课(七月在线出品) - P7:谷歌面试题精讲 - 七月在线-julyedu - BV1Xf4y1r74s
🎼,我们这堂课的主要内容是google面试题精讲。我将从如下几个方面讲述本课。首先讲一下关于面试的一些心得,然后讲也是本节课最重要的6个例题。从简单到最难google的6个面试题,最后总结结束本课。
关于面试,有些人会问了,各个公司到底有没有自己的面试的题库,其实这个问题没有太大意义。因为即使有的公司有题库,这些题库里面的题目来源。一方面是员工原创的这些题目相对比较少。
另外他们也是通过网络来搜罗到的一些题目。所以即使公司有自己的题库,他们的题库交集,也就是重合度也会很大,所以没有说这个题目只被某个公司面这个可能性不大。所以我们比方说关注某一个公司的面试题。
其实并没有太大意义,应该关注所有公司的面试题。因为他们这个交集非常非常大。那另外一点是呃笔试和面试,那笔试大家都很熟悉,发现卷子闷头做就好了,没有任何和面试官的交流。
面试是需要你展现自我展现思路的这么一个过程。你需要和面试官交流,很多讲面试的书也讲不要把面试当成笔试。面试官希望也需要你和他交流。😊,这样才能展现你的思路。面试的关键点并不是你把所有问题都解决。
而是你给面试官留下了一个很好的印象。当然,解题是留下好印象的一个很重要的条件。但光解题是不够的。你需要跟他交流。即使有些问题你可能不太能完全解决。你能想到什么地步说出来也比完全什么都没交上去。
没说出来要好一些。所以总的来说,你要向面试官展现一个你的一个好的这么一个印象。😊,下面是本节课的重点,也就是6个google的面试题。从简单到难。
我先讲最简单的给定一个数N求不超过N的所有能被三或者5整除的数的和,比方说N等于9能被三整除,就是3加6加9能被5整除,就是一个5加起来等于23。显然它是个数学问题,我们可以每举能被三整除的数。
发现是这样的,N除以3加中括号是下取整,在C加加java里面不用加这个就可以直接做。那五也一样。那这两个序列里面是有重复的,重复的数是既能被三整除,又能被五整除的数,它们是三和5最小公倍数的倍数。
也就是15的倍数。那么它这个写出来是这样的,这三个都是等差数列,我们关键就对等差数列求和这两个加起来减去它就可以了。那注意到是面试题,我们需要问一下N的范围有多大。
会不会超过int要不要使用longlong。所以这个需要和面试官交流。因为。😊,这个序列本身等差数列的这个序列的和是N方的这个级别的,所以很有可能就超过int了。当然面试官一般会告诉你。
不用考虑这些问题,但是你需要和他交流。那,做起来很简单,首项项数公差,我们就可以求出尾项,尾项就是D乘以Y减1加上X,这是尾项。所以求和公式就是首项加尾项乘以项数除以2。那注意这个对Y等于零也有用。
因为我们这种下取整很有可能比方说N小于3或者N小于5,N小于15的话,项数就是0。我们乘一个零上去也没有关系。所以和也是0,所以我们不需要对零做特殊的处理。那关键就是这个项数Y了。😊,啊,对三来讲。
首项公差都是3项数就是N除以3,这个自动下取整,这是指的这个语言里面的那五也一样,那这两个加起来减去5就好了。所以这个。程序现象也非常非常简单。😊,写一个函数,接受三个参数,直接return这个东西。
然后主函数里面调正函数调三遍,写一行,直接加两个减一个return回去就好了。所以核心代码就两行一行,这个一行两个加一个减写到一行上面去就完了。所以这是一个非常简单的问题。😊,那我们讲第二个问题。
如果一个字符串只包含ABC3个字母,并且相邻的三个字母。如果不同就是合法的,相同就是非法的。这个呃相同是全都相同,不同是只要有一个不同就可以了。问长度为N的合法的字符串有多少个。
比方说这个是非法的3个B。这个就是。合法的,因为这个没没有相同的,这个是非法的。那么它可以用动态规划的思路来解决。尽管它不是一个优化问题,因为我们强调动态规划是解决优化问题的这是一个组合数学的问题。
但是他们的思路很像,都是递推。我们在状态上做地推。😊,动态规划是在状态上做递推,求max min组合数学是在状态上做递推,累积求和,所以只是这么点差别,不是一个优化问题而已。思路是相近的。
比方说我们这样表示状态,长度为I,最后两位不同的合法串,我们认为是I0长度为I,最后两位相同的合法串,我们认为是I1,那怎么推呢?长度为I,最后两位不同的。我们认为长度I减1,如果最后两位不同。
比方说一个是A,一个是B,那么我可以在最后加上一个C,也可以在最后加上一个A,但是不能加B,因为最后两位要不同,所以有两种情况。那如果最后两位相同,比方说最后两位都是A。
那么显然最后可以加一个B加一个C,因为最后两位也要不同。所以无论是哪种情况,我最后都可以选择两个字母加上去。所以这个最后两位不同的情况是这样的。那如果长度为I,最后两位相同的时候,😊,那我们看一下。
如果前I减一位最后两位不同,比方说一个A1个B,那么最后一位只能加上一个B。因为我希望它们相同,只有一种情况。那如果这个DPI减1一呢,如果最后前I减一位最后两位相同,那前A位我还让他最后两位相同。
那么最后三位都相同了,这是一个非法的,所以不能加上那个东西。😊,所以我们得到了这个递推式,有了递推式,有了初值,我们就可以求出任何的值来。😊,我们看一下初值长度为一的最后两位不同的串,我们认为是三个。
因为根本就没有两位。所以ABC3个都是认为最后两位是不同的那一一显然是个0,因为。还是刚才那个道理,长度为一没有两位数,没有两位的话,最后两位相同。那显然是没有的那最后的结果就是这么一个东西。
DPN0加DPN1。因为最后要么最后两位相同,要么最后两位不同。我们根据这个递推式这个初值求出了这么一个结果。那注意我们可以空间上优化一下这个。😊,这是最后两位。
DI长度为I的最后两位相同或者不同的值与I减1有关。看DPI只与DPI减1有关。那么我们第一为没有必要存N个,也就是没有必要存一个N乘以2的数组,直接优化掉就可以了。那时间复杂度显然是ON的。
因为我们推这个式子要循环N次。那其实当N很大的时候,我们有一个类似于求费摩纳器数列的这种方法,利用矩阵乘法,可以把时间复杂度优化到logN。有兴趣的同学可以去查阅一下相关的资料。
那我们看一下另外一个问题。这个问题相比第二个问题就稍微拿了一点,也是一个组和数学的问题。给定一个整数数组里面包含了0到N减1的一个排列。什么叫排列呢?就是0到N减1,每个数恰好出现了一次,且只出现一次。
换句话说,我把这些数0到N减1这N个数打乱了一下,放到数组里的。那如果我们每次只允许把某一个数和零做交换,只允许这一种操作。问,把这个数组排好顺序,至少要交换多少次。
排好顺序是指把零放到A0上一放到A1上N减一放到AN减1这个位置上。那这个也是google的一个面试题,并且它出现了这个在pet这个里面了,不知道是先被面试的,而先出现在这个pet的这个能力测试里面。
😊,那首先组合数学里面有一个概念,就是圈的概念。我不讲这个具体这个概念,大家感兴上认识一下。比方说零占了一的位置,一又占了二的位置,就是说零应该在A0,但是呢它却放在了A一上面去。而一呢应该在A一。
它却放在了A2的位置上去。那二呢应该在A2,它却放在零的位置上去。我们这样就有了这么一个圈,这就转圈了。我们把这个圈里面。😊,交换一下就可以排好顺序。首先有一个呃可以理解为定理吧。
一个排列这种顺序的排列按照这种位置划分关系,它总可以划分为若干个不相交的圈,不相交的圈就是这样的,每个圈显然有一个长度。那对于一个圈来讲,我们可以通过交换把它排好顺序。
比方说刚才说的这个我们交换零和一再交换零和2就排好顺序了。大家可以画一下。😊,所以有一个结论,如果一个长度为M的圈儿。包含了零,因为我们只能和零交换,则交换M减一次,可以把这个圈里面的数换回原位。
大家可以画一下,但是这M减一也是最小的,为什么呢?因为这M个这长度为M的圈,每个数都不在自己的位置。那么我至少要交换M减一次,才能把它换回自个自己的位置。因为我每一次交换只能和零交换嘛。
至少要交换M减一次。那另外是说一个长度为M的圈如果不包含零。那么我这个圈自己并不能来回交换。因为我只能和零交换,则需要交换M加一次,比方说一在二的位置,二在三的位置,三在一的位置。这样的一个圈。😊。
我必须要先交换零和任意一个数,这样的话。比方说我交换了零和一,那就变成了一在零的位置,而零呢在二的位置,二在三的位置,三在一的位置,这样就变成了这个长度为M的圈包含零的问题。那它我们已经说了。
可以M减一次,最少交换到原原位。那么我这个。总体来总体来说,因为它这是这个相当于M加一的时候,需要交换M次。那之前和零又交换了一次,所以总体来说需要M加一次。😊,并且这个也是最少的。
因为我们只能和零交换,不得不和零先交换一次。那问题在于我们怎么找到所有的圈以及圈的长度。其实非常简单,我们沿着这个数组走,把标把走到的数标记一下就可以了。代码非常短。我拿的是我pa上的那个代码。
那这个其实就是找圈,我们对每个数找个圈。那注意这个有可能这个数已经在自己的位置上了。所以这个R最后是0,R是0,显然要返回零。那R是一的话,😊,这个有可能是2减1,有可能是2加1。
这个就取决于我们这个零在不在圈里,注意零在圈里就是have等于t。所以最后看一下have决定返回的是2减1还是2加1。就是这么简单的一个问题。所以这个本质是大家对于组合数学以及圈的概念的这么一个理解。
所这个也是一个非常简单的问题。重要的函数就是这么一个D,它算了每个数字所在的圈的长度,然后决定一下是减一还是加一,取决于零,在不在这个圈里面啊,我们需要一个布尔数组做标记。😊。
那这个问题其实我在ON时间内解决的问题,下里面讲到过,它也是google的一个面试题,讲出来非常简单,但是大家自己思考还是挺困难的。给定一个1到N之间的排列,呃,什么什么排列,刚才讲过了。
每个数只出现一次。😊,并且全都出现,且只出现一次,就相当于把1到N打乱了一下。我每次可以选一个数,把这个数放到序列的末尾。那问至少几次能够排好顺序?那显然一我没有没有必要动,因为一是最小的嘛。
我们为什么要把一放到末尾?如果我们把二到N都排好顺序,那么一显然就已经在开头了,不会放到末尾去。所以一我们没有必要动。因为一即使我们动了,也只能把它放到末尾,我们要动一先把一放到了末尾。
然后234那些数都要放到末尾,这显然不是一个最优的解。那关键问题是。如果某某一步把X放到末尾,因为我们只能把某一个数放到末尾,我们必须把X加1X加2,以及就是说比X更大的那些数一个一个的放到X后面。
不然它就排不好序了。因为X加一一定要在X的后面,X加2一定要在X的后面。那如果我们选出一个X,也就是说我们要把大于等于X的都排好都放到末尾一个一个排好序,否则就排不好顺序了。
那关键问题是我们这X选的越大,我们要移动的数就越小。因为我们要移动的数就是这个N到呃X嘛,所以是N减X加一个,所以X要尽可能大。那前提是我们选择了一个X,那么前面一到X减一,必须是按照顺序出现的。
所以我们就相当于从开头扫描一下。看一下X最大能达到多少。也就是说我们从开头找一下呃,一出现没出现。2是不是在一的后面。3是不是在二的后面,4是不是。😊,在三的后面,也就是我们从。
开头找到最长的从一开始的这么一个有序的序列。那么这一段是可以保留的那后面那些我们只能从一第一个不满足条件的X开始把它一个一个移动到后面。所以这是一个非常简单的ON算法。但是我觉得面试要突然被问到了。
并不是那么容易想到的,这也是google的一个面试题,代码非常简单,假设输入数数组是A,我们我们要检查一下,从一开始检查。😊,顺着循环。如果找到一,我们就看看二能不能找到。如果找到二。
我们看看三能不能找到。那最后我们发现从找不到的那个数开始到N都要移动一下。那么显然移动的次数就是N减antt加一。因为w是我们第一个找不到这么一个数,前面都能一个一个按顺序找到。那后面那些数都是非法的。
我们只能从w到N一个一个的移到这个序列的末尾,所以这个是非常简单的一个ON的算法,也是我比较喜欢的一个面试题。😊,仔细想一下,并不是那么简单。呃,例五是讲一个BFS的问题。
这个题目也是google的一个面试题,给第一个矩阵啊,比方说右下角这个矩阵X表示起点,我出发点点呢表示就是空的位置,这个井号呢表示墙外表是终点。我问我从起点到终点至少要走多少步。
当然每次是上下左右4个方向,就是普通的矩阵也不能走出去。那第二个是如果我最多拆三堵墙,比方说把井号,最多我扔掉三个,当然变成点了,至少要走多少步。😊,那显然第一问非常简单。
第一问就是一个经典的BFS没有任何难点,就直接做一个广东优先搜索。关于BFS的这个细节。大家可以看一下我讲的这个也是BFS的一一个一个公开课吧,这个比较简单,直接用队列做就可以了。第一问。
所以第一问不细讲。那第二问怎么拆三堵墙。那显然我们可以枚举从N方个假设有这么多强。当是强的这个大概估计了一下是N方级别的。因为最多这个N是行和列。我们假设它是方的。😊,选出三堵墙来拆,这就N的6次方了。
再做BFS又一个N方。所以总的来说,每举这个在BFS达到了一个N的8次方的算法,这个算法的时间复杂度是不可接受的。即使N等于100这么小的数,N的8次方是啊,十0的16次方左右。
这这种复杂度是没法接受的。😊,那我们想一下有没有更简单的办法。其实我们可以建一个四层的图,大概说一下思路。我们每拆一堵墙,我们认为这个图上升一层,从第I层到第I加一层。那不拆墙就在第零层的范围里面活动。
拆墙就从第零层到了第一层,再拆一堵墙,就从第一层到了第二层。虽然每一层看起来是相似的,关键是层与层之间的连边,关键问题在于这堵墙我拆了,从这个位置开始,我做BFS的话,不会再回到这个位置。
因为呃重复的重复的位置是不记的。所以即使我在上一层这堵墙,我把它看成没拆也没有关系。我从这堵墙继续出发就可以了。什么意思呢?😊,每一层先看一下每一层,每一层是相同的,每个点包括墙到它的非常的邻居都有边。
什么意思呢?就是。强到墙是没有强到这个墙是没有边,所以这个墙是有出边,没有入边的,每个点知道自己的非墙的邻居有边。那这个点包括墙,因为墙有触变没有关系,反正我们现在目前位置是进不到墙里的。
这么建图是一种比较简单的方法。因为后位后面也比较方便。我们可以从墙出来。这是因为从一层到另外一层的时候,是可以从墙出来的。我们再看一下怎么建每一层我们把它建成了一个有向图,大概是这个样子?
那么关键是每一层到上一层第I层到第I加一层,那这I当然等于012,一共有01234层。那第I层的任意位置的邻居,这个任意注意可能是墙第I层的任意位置,邻居如果是墙的话,就一条从第I层到该位置。
第I加一层对应墙的边什么意思呢?第I层的邻居,某一个点的邻居是墙。那么我把这个点指向它上一层那面墙。😊,把它到那个墙指一条边,本来它应该指到本层的这个墙,我把它指到上一层。那么这样指的意思是说。
我我相当于从第I层把这面墙拆了,让它到了第I加一层,尽管在第I加一层那个位置还是墙,但是我可以从第I加一层那个墙出去。因为我们注意墙是有出边,没有入边的。所以虽然它是墙。
我们相当于在第I层把这个墙穿透了,穿到了第I加一层那面墙上去,然后再从第I加一层的墙里面出来,再继续走。注意我们这个图只有下层到上层的,没上一层表示拆一堵墙。那每一层。😊,内部都是一样的,都是相似的。
所以我不断的这么从第I层到DI加一层这么走,每走一层表示拆一堵墙,我一共就四层,相当于拆了3,最多也就拆三堵墙。然后这个起点位置和终点位置都是不变的。
那么相当于在这个立体的图上做BFS所谓立体图是因为我们这图有三层,每一层是一个平面,每一个平面里面都是一样的。平面与平面之间就是我刚才说的这种建图方法,从DI层到DI加一层。
他们这两个是邻居的这个墙的位置,这就可以连上一条边。那么大家想一下,节点数是N方边数也是N方,其实是4N方或者8N方的样子。😊,然后时间复杂度也是方的,这比那个刚才讲那个N8次方的那个算法要快了很多。
那这是一个巧妙的建图的问题,也是1个BFS的这么一个推广。那接下来要讲这个本节课里面最难的问题,给定一个字典,找到两个单词,它不包含相同的字母,且成绩最大。当然这个成绩指的是长度的成绩。
当然允允许预处理字典。那它是一个开放问题,其实是没有标准答案的那需要和面试官交流探讨,注意打开思路。那么最简单直接的算法,当然是枚举了,枚举至少要有N方的复杂度。因为字典里面有N个单词的话。
我们需要枚举N方和 pair嘛,那要判断一下,如何判断不包含相同的字母。那我这N方只是每举的复杂度,没有说怎么判断不包含相同字母。显然。😊,我们可以对每个单词用beat map表示,或者说用哈西。
用各种方式表示它里面包含了字母。然最直接的方法就是做一个签名,也就是用二的26次方这么一个beat或者说这么一个整数来表示。哪些字母出现了?如果出现了,在该位置是一,没出现是0。
那么假设呃这里面假设大家对未运算都很熟悉,就是出现的位置是一没出现的这个字母位置是0。那么如果两个单词的签名是X和Y的话,这里面XY是两个int。那么如果X和Y做一下安慰语,那安慰语的意思是说。
两个位置如果同时出现一。😊,那么这个安慰语一定是非零的,因为结果那一位也是一。那如果没有同时。同位置的一出现结果就是零。所以这两个安慰语如果是非零的话,就说明这两个单词包含了相同的字母。
所以我们把每个单词表示为一个整数,这整数就是最初说的。如果这个字母在这个单词出现。这一位就是一,否则这一位就是0,这里面位是指的二进制的be。那么做一下安慰语,就能判断是否包含相同的字母。
这个思路虽然比较简单,但是前面的枚举已经N方了,那N多大我们可以接受呢?比方说我估计N是一两万的时候,我们这么做是可以的。那假设N是100万,也就十0的6次方,N方就不可接受了。
因为达到了10的12次方。😊,那我之所以讲的这里面讲的这个细节,如何判断相同字母,是因为它对我们对于我们这个后面这个方法非常有效。我们预处理字典,假设空间足够大。我们如何表示单词,还是刚才那种表示方法。
每个单词用0到2的26次方减1一个一个这个整数来表示,就每个整数就表示这个单词是否出现了这个字母。比方说A,我们认为A就是第零位是一。那么单独的一个A就是一。那如果是AB,我们认为其实二进制就是11。
其实就是3,如果ABC我们认为就是111就是7,那如果是比方说AC那我们认为没有B嘛,我们认为它其实是101,那其实它就是二进制的101,实际上就是5。所以每个单词我们都可以这么表示。
我们不用担心这个字母出现的次数,我们只担心它出现不出现。因为这个问题里面也只要求没有相同字母,并没有考虑每个字母出现的次数。所以我们只需要用01表示字母出现不出现就可以了。
所以对于这个签名还是非常好理解的。关键看我们怎么预处理这个字典。😊,那关键问题是我们如何表示一个字母的集合。什么叫字母的集合呢?就表示一个集合里面的字母。😊,哪些?
就是我允许出现的字母是这个字母的集合里面的。也就是我给定一个SS还是按我们刚才的那种表示方法就是。😊,也就是我给定了一个SS还是按照我们之前的那种表示方法,这个出现是一,没出现是0。
我这个S跟刚才那个单词表示,虽然形式上是一样的,但是它的意义不一样。我这个S里面唯一的位表示我希望我得到的那个单词,出现的字母一定是这个S的子集,什么意思呢?😊,比方说我S是111,嗯,也就是S是7。
我表示的是我希望我这个单词里面只出现ABC这三个字母,但是可以不出现。也就是这个单词里面出现了字母一定是ABC的子集。刚才那个含义是说这个单词里面出现了ABC这个字母,所以表示成7。
我现在这个S的意思是S等于7,我表示这个单词里面只能由ABC3种字母来组成。但是可以不出现。比方说只出现A的。😊,它也在我们这S的含义里,出现AB的,它也在我们S这个含义里三个字母都出现了。
也在我们的这个含义里,只出现B的,也在我们这S的含义里面。所以它的意思是说。😊,出现的字母是S表示这个字母子集的那些单词里面最长的。那S怎么表示子集就是出现是一,不出现是0。
也就是我这个单词里面出现的那些字母,恰好是S里面标志为一的那些位的子集。😊,我想表示这么一个东西。😊,那DPS就是我刚才说的那个含义。😊,我希望得到。
由S表示的这集合子集里面的那些单词里面最长的还是这意思。比方说S得7的话,DP7的含义就是。由ABC组成的单词,包括仅由A组成单词,包括仅由B组成的单词,包括仅由C组成单词,包括仅由AB组成单词。
包括仅由AC组成单词,也包括仅由BC组成单词。当然也包括ABC同时都出现的这个单词,所有这些单词里面最长的这是DPS的含义,也就是S表示允许出现哪些字母。当然不一定全都出现。但是只要出现了一定在S里面。
那么我关键是如何算出这么一个东西来。那么初值当然我敢给它把它全都复成0,认为这个最长单词长度是0。关键我们怎么更新它。对于每个单词,如果它签名X。
我显然可以把这个这个lesss word就表示这个单词的长度,我显然可以把它更新一下,因为这个X就表示虽然它是X子集X本身也是X子集。所以它可以用自身更新。关键是我怎么推。
这里面实际上DPX就得到了出现的,恰好是X那些字母并没有那种子集关系还举刚才那个例子。比方说DP7。😊,在这个初值初始化之后,DP7表示的是由ABC。全都出现的那些字母的这些单词的长度。
也就是说A肯定包含ABC,并且A也出现了,B也出现了,C也出现了。也就说没有一个子集的关系,恰好是这个三个字母同时出现的那些单词的长度。那我后面还要更新,要把子集算上去。
就是只出现A的算上只出现B的算上去,以及这个出现AB的。就刚才说的那些不全出现ABC的,但是出现的是ABC子集的那些单词算上去,怎么更新呢?😊。
注意我这个S是我要算的这个集合S从一循环到2的26次方减一,枚举所有状态。那S撇是比S少一个一的,这个一是二进制,少一个一的这么一个状态。那注意比S小的状态,我已经算完了。那么这S撇我已经算完了。
对每一个这样的S撇我都更新一下,取最大就可以了。这是一个动态规划的思路。我们来看一下为什么。S撇R小于S已经算好了。那我假设我们想计算,假设我用二进制表示,我们想计算这个状态,1010,这是S。
那么它可能的S撇是把首位变成零,就是01010,还有第二位10010,还有最后一个11000,每一个一变成0有3种状态,注意这三种状态已经算好了。也就是说我我们已经得到了这两个一的子集里面的最优值。
这两个一的子集里面最优值,这两个一的子集里面的最优值。我现在想知道这三个一的子集的最优值。那它显然要么就是。😊,上面这三个里面呢,因为这三个一的子集包含了这两个一,这两个一,这两个一的全部的子集。
因为这个状态比这个状态小嘛。比方说这个呃我认取一个一这个一吧,前面都是零。那么它显然在这个子集里面含着,当然也在这个子集里面含着。所以这个的真子集一定是这三个东西的子集,当然有可能是某几个的子集。
但是没有关系,因为我存的是最优值。那另外一种情况就是不是真子集,不是真子集,就是它本身它本身我们在预处理已经处理过了。所以。😊,这个最优解这个状态下,最由解要么就是它子集的状态的最优解。
它子集就是至少比它少一个一嘛,真子集就是这个的最由解,要么就是它本身它本身这已经算过了,就是三个一的那个,所以就是这样DPS要么就是DPS本身,要么就是比它少一个一的状态的子集。
因为这个DPS撇已经不是这个恰好等于S撇的了。已经包含了S撇的所有子集了。我们现在在更新DPSDPS还是恰好等于S的。我们这么更新完了之后,DPS就包括了S的所有子集,原因就在这儿,刚才已经讲过了。
要么就是这三个的某一个子集,要么就是全集本身,所以这个已经更新好了。那我们看一下答案是什么。😊,我们对于X来讲。假设我们选择这个单词,那lesss X我表示并不是X的长度,是这个单词的长度。
那另外那部分显然不能和X有相同的唯一的位。那不能和X有相同的唯一的位。那么显然就是和非X嘛,因为相当于X为一那些位,这些位全都是零,其他的那些可以出现,可以不出现X为零的那些位可以出现,可以不出现。
那么在这里面我们取一个反之后,那么X为零的那些位,显然。😊,都变成一了。那么他选的一定是那些一的子集S为一的那些位显然不出现。那么我和它做一个语的话,就是呃只取了它的第26位。
所以大家对微运算一定要很熟悉。那这个取最长的,这两个一定没有交集,因为这个不可能同时为一,这两个没有交集,并且这个是最长的,这个是没举的,所以最后每举所有的单词,这个预处理出来就好了。
那么我们算一下时间复杂度。首先每个单词计算签名,就是计算这个X要每个单词的长度乘以N。因为我们要微运算把这个出现没出现标记上去,这个并不是很大。😊,然后这个。计算这个是很大的时间复杂度。
是二的26次方乘以26。在这里。这是二的26次方。然后我们找这个S撇RE要看一下哪一位是从一变成零的。所以这儿还有1个26的循环。就像我们在这儿需要把这个一变成零得到的是这个,然后把这个一变成零。
得到的是这个,然后把这个一变成零,得到的是这个。所以我们真正循环要循环26次,把每个一都变成0,所以这个是计算DPS的复杂度。那最后求解还有一个ON,因为我们我们要每举每一个单词算一个这个东西。
那这个题比较难,大家要熟悉一下微运算才能真正的理解。那空间复杂度是2的26次方。因为我们要保存所有的这个DP,我们打出了是DPS的这么一张表。那难点理解微运算,理解那个DP的含义。
刚才讲了当前集合的子集,也就是我那些一的这三个一的子集,要么就是两个一的子集,要么就是这三个一的全集。所以就是这个意思。😊,当前集合的子集,包括比当前集合少一个元素的全部的子集,还有当前集合本身。
所以这个就是那个S撇R,这个就是S。那么我们可以把DP映射的整数理解为实际单词。因为我们这里面只存了单词的长度。我们真正存单词其实是一样的。那么我们就可以得到真正的那两个单词在哪,就是只是不存长度。
存的是具体那个单词呃,思想是没有区别的。那做一下本节课的总结。首先一定要和面试官交流。刚才已经强调了,不要把面试当成笔试,要给面试官积极的情绪。即使你不会做这个问题,也要跟他交流探讨。
很多问题没有标准答案。比方说我们今天讲的这个最后这个问题,虽然它比较难。就是因为它比较难,所以他没有一个非常标准答案。我给的第二个解法,虽然就是复杂度看似好了一点,但是它的空间复杂度很高。
2到26次方也不是一个很小的数,还有。😊,多提假设。就比方说那个第一个问题,这个等差数列那个问题,函数头部其实是需要自己写出来的。我刚才说了,超不超不超过long long,超不超过int。
大家需要跟面试官交流清楚。那google的面试题,其实不光google很多公司的面试题都没有固定的套路,我们不要试图去找出这个有哪些套路,有哪些规律可循。其实面试官出题也很随机的那多总结多思考,多归纳。
才能有感觉。那祝大家好运。😊,好,今天的课就到这里,希望大家给我提出批评指正。
人工智能—面试求职公开课(七月在线出品) - P8:链表面试题精讲 - 七月在线-julyedu - BV1Xf4y1r74s
。大家好,欢迎观看7月算法公开课。我们本堂课的主要内容是链表面试题精讲。我将从如下几个角度阐述本课,先讲一下列表的简介,然后总体分析一下近些年来链表相关的面试题,做一个知识点的梳理。接下来讲6个例题。
最后总结结束本课。关于列表的简介,大家非常熟悉链表的一个特点就是一个元素只能通过指针来连接下一个元素。这个指的是单链表,我们不能在长数时间内访问DK的元素,这个和数组不一样。
数组呢直接在下表里面我们就能访问DK元素。列表只能从表头一个一个找过去,它的分类呢就是单链表和双链表,呃,单链表呢就是只有下一个节点的指针,双链表有一个朝前指的一个朝后指的指针。
另外一个分类就是循环链表,这个是它和单链表双链表本身并不是这个独立的,也就是它和单链表双链表都有交集,它是指的这个首尾相接。我把最后一个元素和第一个元素连起来形成一个圈,这个就要循环列表了。
那编程语言里面java有link的listC加加呢STL里面有listC没什么好说的,只能通过指针来实现链表,这是最基本的一个陈述。😊,关于面试题。其实链表的面试题都不是很难,但是很繁杂。
主要涉及的就是链表的比较基本的操作,包括插入删除翻转。这个翻转有多种,一种就是从头到尾都翻转过来。第二种呢是给你一段区间,比方说第M界面到第N个节点把它翻转过来,其他地方不能动。
还有一种呢是我把它分成每K一组,每K一组,每K给翻一次啊,但总的来说都是翻转,还有涉及到列表排序的,比较经典的就是规并排序。这里提到了,还有快排的partition。还有一种类型是复杂列表的复制。
这个在后面有例题。嗯,再后面呢这个链表,这个指的是单链表问有没有环。如果有环的话,环的起点在哪里?环的长度有多长?这个是。啊,后面有个例题在说这个。然后链表的倒数第K个节点,这个其实可以通过快慢指针。
我只要快指针和慢指针相差K个节点,这样我扫一下就能找到倒数第K个节点。当然我们也可以先统计出链表的长度,然后再找DK个节点都可以嗯比较简单吧。还有一类是随机返回列表的一个节点,要等概率的。
这个其实不属于列表的范围,它属于随机采样的范围,我只是从全面性的角度把它列出来了。还有一个是链表和其他数据结构,主要指的是二叉数,二叉数和双向链表之间可以相互转换。这个我本来举了一个例题。
后来时间关系把它删掉了,会放在数和图的那一张里面讲吧。😊,那我们先来看第一个例题,链表的插入与删除,这个是最基本的操作了。所以这个只是列出来让大家熟悉一下基本操作。我讲最简单的那个类型就是单链表。
单列表怎么插入呢?遇到链表的问题,我建议大家现在纸上画一下要做哪些操作,一画就明就明了了。😊,我们需要考虑哪些指针需要修改啊,显然这个列表之这个节点之前的那个节点,也就是前驱节点的nex指针显然要变掉。
因为要指向这个新节点,那新节点自己的nex指针肯定要变,要指向这个原来前区的这个nex。所以我们至少要改变两个指针。😊,那我们插入一般要找到插入之前的那个节点,也就是我刚才说的前驱,那有什么特殊情况呢?
在head之前插入,这里面其实还包括had等于空had就是表头。如果表头等于空,根本这个列表就没有东西,那我们插入就只剩下一个东西了。那这种情况其实和在head之前插入可以统一起来。
我们直接n就作为这个新插入的这个节点。假设我们已经构造好了,我们把这个notode next等于head把ha等于no。其实这两步就做完,就把它插入了。这步这个特殊情况其实就是说插入之后,表头变了。
大部分情况都是在中间插入,插入之后,表头不变。因为我们列表的问题一般都是比方说写一个函数,传进去一个表头传回来还是一个表头。😊,因为这个链表会有变化,我们只有通过表头来访问链表。
所以链表的问题都是传入一个表头,传出也是一个表头,表头非常关键。所以我们非我们要考虑的非常清楚。那一般情况呢就是。这个样子我刚才说了,改变两个指针,这个就是改变新节点的指针。
这个呢是改变前区的那个nex指针。注意这两个顺序,因为我这个要附成这个,所以我必须要先改变新节点的,再改变pread。所以这个比较简单。😊,那删除呢其实差不多,哪些指针要修改,其实就是前期的nex的。
把它跳过去就可以了。把它指向它的next的 next就可以了。特殊情况表头会变,我把表头删了,有可能。😊,那其实这个如果链表里面只有一个元素的话,我删了之后,它就是no。
因为temple这个head的下一个就是n。那我们在fr后面删除的话,怎么删呢?先把pde的下一个节点记下来,然后把pread next复成这个,再把p,就是原来pread的下一个节点。
也就是我要删的那个节点空间释放掉。所以这个删除也就这么几步,非常简单。😊,那,给大家几个思考题。刚才我讲的是最简单的情况,就是单向列表,还有双向列表怎么插入,怎么删除。还有一个是循环有序的链表。
就是这个链表本身,比方说12345。😊,这是一个有序的,并且呢它把五跟nex的指向一了,就是在一个圈里面。那么我要删插入一个节点,这个其实还是有点困难的。比方说呃我插入的节点有重复值。
或者我插入的是最大的最小的等等,插入的位置怎么选取,要把它想好了。不过我个人建议是先把它断开,然后插好了之后再把它最后一个节点指到第一个节点上,这样不容易错,但是其实有很多不用断开它。
这个就是加了很多条件判断的方法也可以做。这个给大家思考。😊,然后这里面我想提一下,就是所谓的lazy delete,就是懒删除。假设我们要删除ow这个节点,这里面要注意,n不是最后一个节点。
那么我们找到n,我们现在就在n这个节点上,我们要删除它。这个在单列表里面一般情况是无法实现的。因为我们必须在它之前的那个节点位置才能把它删除。那现在我已经到了这个节点,我怎么把它删除呢?
有一个比较懒的办法,就是我把n的下一个节点复制过来啊,我这里面假设这个n只有一个字段,就是X,就是只有一个整数值,我把下一个节点的内容信息都复制过来。那这样的话。😊。
note本身和note下一个节点长得都一样了。那么我再把note next删掉。实际上这个并不是真正的删除note,我是真正删除的其实是这个这个节点,我只是把用n把它的。这个下一个节点复制了一遍。
再把下一个节点删除。所以这个是一种删除方式。然后我再讲第二个例题。单列表的翻转,这个非常简单,我就快速的讲一下。这个前两个例题都是帮大家理解呃,链表的最基本的操作。
那么翻转其实就是把当前节点就是这个节点拿过来作为已经翻转结果的表头就可以了。因为我们可以改变列表的顺序嘛,就是类似于一个对战的这个假设我前面已经翻好了。我把这个节点拿过来作为新的结果的表头。
那么前这些节点都已经翻好了。我们看一下,非常简单,result就是我翻好的这个链表的结果。那么我先要保存当前这个节点的下一个节点。因为我下一次循环就要翻这个节点了。那么我现在要翻的就是ha这个节点。
那headd节点的nex等于我之前翻翻好的那个节点的表头,那么表头变一下就是结果的表头变一下,那么headd变成它原来的下一个节点,所以这个顺序很重要,主要强调一下顺序,并且呢这里面就是ha为空啊。
那些情况,其实都已经在这个里面隐含着了。因为head为空result肯定为空,并且这个呃翻转之后的最后一个节点的nex。😊,肯定也是空。因为第一个节点就把headd next等于result了。
还有一个就是顺序要注意,先把这个节点保存下来才能改变它,不然链表就断掉了。前两个例题都非常简单。那思考题。就是刚才我说的呃,如何翻转一部分列表,比方说li code第92题。
就是翻转第M元素到第NN个元素之间的那一段。那其实我们需要把它从DM元素之前断开,第N个元素之后断开,把M到N翻转了,翻转之后还得再连回来,连回来的时候。
就是前面那部分就是DM元素之前的那部分的最后一个元素我们必须得有。因为我们要从最后一个元素把那个翻转那部分接回来。那后面那部分第N个元素,最后那部分的第一个元素我我们也必须有还得接回来。
那还有很多特殊情况需要处理。比方说这个M等于一,也就是这列表DM元素之前没有东西怎么办?第N个元素后面没有东西怎么办?所以很多特殊情况需要考虑,尽管这几部说起来非常简单。
另外一个就是刚才我说的li code第25题,每K个元素翻一次一样的。😊,同样我们把前面翻转好的部分都保存好,现在要翻转这K,把它单独截出来,翻转之后再把它连上来。那后面没有处理的,还要再继续处理。
还有如果最后有余数不足,K怎么处理?所以有很多细节的问题,说起来都不太难。这个留作思考题,我们再讲第三个例题。😊,第三个例题其实呃比较经典,它是说给你一个单链表问这个链表是否有环。
其实就是说这个链表可能建错了。我最后一个节点的nex的不是空,而是它指向了前面的某一个元素。这样的话,列表就转起来了。我如果连着沿着链表走,它就会转起来,这个没没有头没有尾。
就是从头直接走走到一个节点走到一个永远走不到尾。那。😊,我们怎么判断这种情况呢?这个是lea code上141、142题啊,141题和142题有一个区别在于有一个题是说,只要判断有没有环就行了。
return一个布尔值出 first。那另外一个题呢是说这个如果有环的话,你把环的起点找出来。就是环的起点是哪个节点。当然这个这个环可能不是从开头就开始这个产生的。
有可能是一个类似于阿拉伯数字6的这种形状,就是它开始有一段,然后才有一个环。所以环的起点也需要求。那我们先来看一下如何找环。😊,最直接的办法就是我们用一个set存放每个节点的地址,注意set里面。
存放的元素必须是有序的,这个序不一定是这个大小关系。你需要给它定一个序,所以并不是任何的object都可以放到set里面。我们需要给它规定一个顺序。那地址就具备这种顺序。其实地址我们可以把它理解为整数。
尽管这种理解可能不是十分的正确。但是其实真正意义上地址它就是一个整数,只不过这个整数我们不能这个做传统的这种加减运算。😊,那最直接的方法,我们就用一个set把经过的节点都存下来就好了。
我们就这样沿着投指针走。如果找到了之前经过的一个节点,那么它显然就是走环绕回来的,就有环,否则就没有环,这个是一个方法。那呃这个它额外用了一个set主要是空间复杂度有一些时间复杂度也有。
因为哈这个set里面查找是log n的。当然我们把它改成哈希的话,呃,就可以做到期望的时间是这个ON的,但问题在于。😊,呃,还是用了额外的空间,有没有不用set的办法呢?我们来看一下。我们用两个指针。
P1和P2P1呢每次走一步。P2呢每次走两步,如果有圈一定会相遇,请大家思考一下,为什么一定会相遇。如果相遇的时候,我们如何找到焦点,那我定一些变量圈长是N起点到圈的起点的距呃。
就是链表的起点到圈的起点的距离,也就是呃那个饼的长度,你可以理解为它是一个横线带一个圈,那个横线就是这个饼的长度就不循环的那个长度是A。那P1。到起点的时候,因为P1是每次走一步的那个指针。
它到了圈的起点的时候,P2肯定比他进圈早。因为它走的快,它在圈的X位置,这个X是指距离起点的位置。我们来看一下。😊,刚才说了,P1到起点后,这个P2已经走了X部了,在圈里面。那么他们相距其实是N减X部。
因为这个在圈里面两个方向,一边是X,那边就是N减X圈总长度是N。那么他们N减X部肯定会相遇。这是一个追击问题。因为这个每走一步距离缩小一嘛,P2走的快嘛,每走一步,他走2P1走一嘛,他们相距N减X。
所以走N减X步肯定相遇。那么。假设我们相遇的时候,相遇点到起点的距离,这个指的是圈起点是B。那么P1走的距离实际上是A加B。其实P1走的肯定小于一个圈。因为P1走的这个呃在圈里面只走了N减X步。
这个圈的长度是N,所以P1肯定没有绕过一圈在圈里面。😊,所以它走的距离就是A加B,因为这个相遇点距离圈是B嘛,这个前面那个饼的长度是A,所以P1走的是A加B。那P2走的是什么呢?
P2其实在圈里面可能绕了很多圈了,可能绕了K圈了。这里面其实这个P1不一定呃P2不一定比P1只走了一圈,只多走了一圈,它可能比P1这个在里面已经绕了K圈了。这个是在P1进入圈之前,P2早就进入圈了。
如果这个饼比较长,圈比较短的话,P2在这个时候已经在圈里面绕了很多圈了。可能但是无论如何它绕了K圈。😊,那么他走了就是A加B,再加上K乘以N,因为N是圈长,K是一个整数。那么右边是怎么回事?
右边是刚才说了,P2走的是2P1走的是一P2的速度是P1的二倍,所以P1走A加BP2显然走了这么多,所以这就有了这么一个等式。这个等式对我们来讲有什么用呢?😊,把A加B消掉,就是A加B等于K乘以N。
这就说明A加B,也就是P一走的距离,或者说丙的那段长度,再加上圈的起点到这个相遇点的那个距离。正好是圈长的整数倍。那这个有什么意思呢?我们在想,我们现在假设两个点已经相遇了,他们相遇的时候。
距离圈起点的距离是B。😊,那么。我们把P1拉回起点,这个不是圈的起点,拉回列表的起点,就是第一个节点。把P2呢不动,因为它就在距离B的位置。那么我们再走。这时候走并不是一个一步一个两步了,每个都走一步。
就是P1走一步,P2也走一步。P,然后P1再走一步,P2再走一步,就这样一步一步走。这样走A步之后,我们看一下出现什么情况。因为我刚才说A的定义是起点到圈的起点的那个长度,也就是那个丙的长度。
所以A步之后,P1肯定到了圈的起点,因为这个A就是这么定义的嘛,P2呢P2,我们在B的位置走的,在距离圈起点B的位置走的,因为相遇点是距离圈的起点,是B它走A步之后。😊,我们有这个式子。
A加B等于K乘以N,它走这么之后,算上B的那段,恰好也是圈长的整数倍。所以P2也到了圈的起点。这时候P1P2又相遇了。所以我们在第一次相遇之后,把P1拉回起点,然后两个指针再一步一步的走。
而不是一个一步一步两步的走走A步之后再次相遇的时候,我们就找到圈的起点了,找到圈的起点,再找圈长就容易了。因为我们顺着那个圈再走一圈,比方说P1不动,P2再走再相遇的时候,记一个数。
那个长度就是圈的长度。所以关键是如何找到圈的起点,圈长是好办的。我们来看一下这有个示意图。😊,这个就是我说的。😡,这个是入口,就是圈的起点,这个是链表的起点。P1进入入口的时候,P2是在这里的。然后呢。
第一次相遇点就是这个红的位置,实际上就是说这个刚才说的这段距离是A红的这段距离是BP1走的是A加BP2走的是可能是好多圈,但也到B了。但无论如何,这个A加上B的长度,是这个圈长的若干倍。
这个刚才已经正了。那现在如果他们在第一次在这相遇了,相遇之后,我把P1拉回来,P2从这走。因为他相当于P2先走了B,在圈里面先走了B。那么。P1走A的时候,到圈的起点,P2走了也走了一个A。
他走了一个A,算上之前那个那个B已经在圈里的B,他肯定也走到了圈的起点。这个就是A加B是圈长的整数倍的应用。他们在同时到相遇的时候,恰好到了圈的起点,我们就找到圈的起点了。那这个是啊一个证明。
那么大家可以看一下我的代码。😊,其实代码写起来非常简单。首先。😊,两个都是头指针,这步就是一个走一步,一个走两步的过程。因为P2快,所以我没有必要判断P1是不是空啊,注意我这里面混用了那个闹值。
就是NULL那个空值和零,这个斜期还比较短这个。如果。P2是空或者P2的nex是空,就说明这个列表是有限长的。因为嗯肯定已经到表尾了嘛。那否则的话我P2就走两步,P1走一步,直到他们相遇。
如果推出这个循环,显然就是有环了。如果在这返回就是没有环。那有环之后,就是我刚才说的,把P1拉回起点,然后再一步一步走,这个是P1走一步,P2走一步。实际上这个推出来之后。
这个P2就在圈的那个刚才我说的B的那个位置,P1拉回来,然后他们在同时走A步,走A步的时候会同时到达圈的起点。这时候P1P2相同了,相同的时候返回哪一个都可以,都是起点。😊,这个就是第三题。
我觉得是比较经典的一个问题。那么第四题呢,其实。我觉得比第三题简单很多。可以看一下,在一个单项列表里面呃,在两个单项列表里面找到他们的焦点,这个是什么意思?两个这是lea code上第160题。
就两个单项列表,有可能他们之间有个交点,大家可以理解那个Y字形就是大写字母Y分出一个叉,后面是一样的。因为单项列表,如果有交点交上之后,后面都一样。因为它nex指针是唯一的。😊。
那我们看一下能不能找到这样的焦点,甚至他们可能这个焦点根本不存在。呃,最直接的办法就是还是我刚才说的,我们用一个set把一个列表里面所有节点都记录下来。比方说A列表,我们先把一个一个节点都存下来。
然后B列表再走一遍。😊,如果遇到了。沿着B列表的表头走一遍。第一个在set里面元素就是他们焦点,这个是一个显然的。但是这个显然是很笨的方法。😊,那我们看这个第二个方法,如果一个列表长是X。
另外一个列表长是Y。我们这里假设X大于等于Y。这个较长的那个列表,我先让他走X减外部。其实可以理解,如果是一个大写字母Y的话,它那个分叉两个叉是不等长的。那么我让较长的那个先走X减Y步。
这样两个列表等长了,然后再一起走,你走一步,我走一步。😊,遇上的时候肯定就是焦点,主要是两个链表长度不一样。这个方法就不用到st,这个比那个好很多也快很多。那方法三其实是我自己想出来的。
是为了这个拓展一下思路,想出来,其实它并不简单。如果我们把第一个链表首尾相接,就我刚才说的循环链表,我们把第一个列表的最后一个元素指向它的表头。那么第一个列表实际上就是个圈了。那第二个列表呢。
如果第二个列表和第一个列表有交点的话,大家可以想象一下,正好就是一个饼,加上一个圈,就是一一条线加上一个圈。那这个。那个圈的起点其实就是它们相交的焦点的位置,但这里面看起来似乎就是容易一点。
但它要找圈儿,要找圈的起点。还有我们最后理论上不应该把这个链表变化,所以还得把我们形成圈那个列表再恢复过来,所以还需要我们从表头找到表尾,然后再把表尾nax值设为空,就是再让我们把这个圈断开。
恢复成第一个列表的样子。所以方法三只是思路的一个扩展,并不是一个很简单的方法,所以我还是推崇方法2,大家可以看一下我的代码。😊,代码一点都不难,大概看一下get lens。
get lens是我自己写的一个函数,返回链表的长度,这个就是R嘛,就是一个一个走走一个加一。所以这个算出来就是列表的长度了。😊,那这个Lance A和L B分别是两个列表的长度。那看一下哪个长。
这个是A比B长,这个B比A长,反正都差不多,较长那个先走那么多步,先走它的差之步。这样的话两个列表一样长了,一样长了就好办了。我一个一个走就好了,每一步走,如果他们最后相遇了,就说明有焦点。
当然其实这个还有一种特殊情况,就是两个虽然一样长,他们同时走到了表尾,所以也返回一个空值,就是had A等于ha B都等于空,这也没关系,反正不相等的时候也要返回空,所以这个统一处理没有关系。😊。
这个是一个比较简单的问题,帮着大家拓展一下思路,它可以用那个环儿的那个思路来做,但是比较麻烦。这种思路相对好一点。我们再来看第四个题。第四个题,我觉得是本节课里面最难的问题。但是它非常经典。
所以我把它列出来了,就是一个列表,这个指的是单列表,除了是next指针以外,还有一个random指针。random指针呢它指向。😊,列表里面的任何一个元素,就是它可能指向任何一个元素。
它随便指这个nex的是指指向下一个,这个没有问题,它就是传统的nex,但random那个指针它是乱指的,它想指哪个指哪个。但虽虽然它是固定的,就是它指的是一个固定的位置,但是这个固定的位置没有什么规律。
它可能比方说第五个元素的random可能指向第三个元素了。😊,当然也有可能为空,这个是lea code上138题,我们的目的是复制这个链表。难点在哪呢?难点在于,假设我们把这个列表复制了。
如果没有random指针,我们就都复制好了。一个它原来什么样子,我们也这么一个一个新建一个节点复制过来,复制过来,把它连起来,都已经复制好了。那random指针怎么复制呢?
难点在于我们不知道这个复制之后的那个random指针应该指到哪儿,在旧的列表里,它能指到某一个位置。在新的列表里,我怎么知道它要指到哪个位置。比方说我还是想把第五个节点指到第三个节点上。
但是我不知道第三个节点的地址,我不能每次都查找一遍。那。😊,这就提示我们笨方法可以用一个map把旧的地址映设为新的地址。😊,我们还是按传统的方法把这个单列表复制一份,复制的时候同时存一下第一个节点。
原来的旧地址是什么?key就是旧地址,Y6就是新地址,这样的话任给一个旧地址,我就能找到它的新地址是什么了。那么。先扫一遍,把它复制好,再扫一遍。再复制这个random,那这A撇就表示A的对应的新节点。
原来那个旧的节点叫A,那么A撇的random其实就是A的random取取这个map就把它的新地址拿出来。等上就就可以了。这里面要注意,如果这个是空值的话,我这个也直接附成空就好了。
所以我map里面有一个空到空的映射,这个倒没有关系。那这个是要用一个map的。其实从这几个题都看出来,有的要么用ex个set呀,这里面用一个map其实都是可以解决的。但是这些都不是最优的。
我们其实是有办法不用这个map来做的,怎么做呢?😊,分三步,这三步,每一步都是最基本的操作。第一步插入我们在每个旧的节点后面加入一个它自身的副本,什么意思呢?我们在第一个节点后面一后面加一个一撇。
二后面加一个二撇,当然他们还是连着的,就是呃最后也就是所有的这个基数位置上的这些节点都是旧节点,所有的偶数位置上节点都是新节点,所以我们在。这个列表里面每个节点后面复制一份自身,这个是可以做到的。
这个做完了之后,我们复制random指针。rananddom怎么复制,我们可以考虑一下一个旧的节点A。😊,它的新的节点,也就是它对应的副本,其实就是A的下一个节点。
因为我们复制就是这么复制的A的nex是它的下一个节点。那么A的random这个指针,其实它是一个旧的节点。😊,那么它是一个旧的节点,根据我们刚才说的旧的节点的副本是它nex的。
所以A的random的节点。的副本其实就是A的 randomdom的 next的,这个是相当于代入一下,就是这样。那么新的节点random指针呢?A的 next是新的节点,新的节点的random指针。
也就是A的副本的random指针。他应该是什么呢?他应该是A的。rananddom指针的副本。所以这个是最关键的。大家可以仔细理解一下。为什么这样新的节点的random。😡。
新的节点的random其实就应该是旧的节点的random的副本。这个就是从这儿来的,因为A的random的副本是A的random next的嘛,所以这个是新的节点的,应该指到哪儿。
那我们看一下旧的节点应该是啊旧的节点应该指到这儿,那么旧的节点的副指到这的副本,就是它的nex了。所以这个等式非常重要。但请大家仔细理解,这是解决这个问题的关键。所以第一步先复制一个副本。
第二步复制random指针,第三步再把链表拆开。因为我们不能改变原来那个列表,那我们再把它还原回来,把旧的节点练成一个列表,把新的节点练成一个列表就好了。那大家可以看一下我的代码。
其实我代码写起来也非常就是不是那么没有想象的那么烦。😊,注意我这里面先判断了一下空,因为在有些问题时候,先处理空会达到非常简单的这个目的,就是少了后面很多判断。那我这边其实也是呃主要的就是三个循环。
三个循环分别分别完成了三件事情。我们先看一下第一件复制。我对每个节点复制一下,现在我要复制n这个节点。那么呃它每个节点有个label,根据这个它的注释,它的n这个节点有一个label,我先复制一下。
复制完了,我就叫copy。那么copy我怎么把它连上去呢,copy next等于n next now next等于copy其实这几步都是连上去过程中中的一些操作。其实我在讲插入的时候也已经讲了。
我这个时候相当于在n后面插入一个copy,但这个差别在于我这个n是一个循环的。所以我最后n要等于copy的n,所以这个n就变成了呃相当于n最开始第一个节点插入copy之后,n变成了第三个节点。
再插入no变成了第五个节点,就是n永远是旧的那些节点,copy是一个新的节点,我产生一个copy把它连上来。这是第一个循环做的事情。第二个循环做的事情,就是我刚才说的。😊,旧节点。呃。
这是旧节点nex的是一个新节点,新节点的random值等于旧节点的random值的副本。当然这里面对空要单独判断,因为它可能指向空。如果不是空的话,它就是这么一个东西。
所以第二个循环就是简单的复制random过程。注意我这里面n每次走了两步。所以那永远是个旧的节点。n next永远是个新的节点。😊,这是第二步过程。那么最后一步就是我说的把它拆分拆分。我刚才说了。
基数位置和偶数位置单独处理。那么这里面。有很多麻烦的点就是在于我在一个链表上连上的时候,我必须得记录那个链表的表尾。那现在如果有一个保证它有一个元素的话,那个表尾肯定不是空,我会省很多操作。
那我大概这样这样做一下就可以了。这个H呢其实就是新的我复制完成的那个列表的表头。它第一个元素显然是ha next的这点在had部为空的时候,所以直接访问ha next没有问题。
那这T呢是我新的链表的表尾。那我旧的列表表头就是ha旧的列表表尾,我就叫tail。所以我用一个字母表示新的列表。呃,四个字母表示旧的链表,这分别是表头表尾。那大家可以在纸上画一下,我这个是怎么做的。😊。
tailll这个每一步都是要把表尾更新掉,因为我永远是要在表尾后面接。那么表尾接什么呢?表尾的后面这个tail next接的其实是T的 next,因为T恰好是它的下一项。
T的 next实际上才是下一个旧的那个东西,所以我直接把它练过来就行了。那这个也一样。😊,这个tail nexttail实际上是旧的那一项。tail next是他的想要的下面那个新的那一项。
这里面要注意顺序,一定是tail和tail next的。因为这个C语言赋值是先执行右面的,所以tail是最后复的。所以这个tail next要比它先复。
其实真正写应该是tail next等于T的 next的,然后tail再等于tail next,但是我这样写就写到一行上去了。这个也是那这里面注意tail先等于零的时候,就等于空的时候到表尾先退出。
因为这个时候访问tail next已经非法了。那这个是列表复制,这个是我们今天讲的最难的一个问题。😊,然后第六题其实相对比较简单,是快排的这个parttition过程,给定一个列表。
列表里面所有元素都是整数,然后让我们再给定一个X,我们把比X小的放到比大于等于X的那些节点之前,其实这是一个partition的过程。这个数组里面就是在快排的时候就这么做了。链表有一个优点。
可以说是优点吧。它和数组不一样的地方在于它做parttition根本没必要这个。😊,根本没有必要那样交换来交换去,它可以自己重新起一个头。我我就是这样做的,它重新起一个列表,把这个比X小的节点连过来。
把这个比X大的或者说大于等于X节点连过来,弄成两个小链表,然后再把一个接到一个后面就好了。但是数组就不能这样做。因为数组这样做,我必须有额外的空间才能这样做。
链表不一样的地方在于我直接把那个节点拉过来就可以了。所以相当于用的额外的空间是常数,这是和数组不一样的地方。所以它写起来没有数组那样交换来交换去的过程。但问题在于它要这个修改很多指针。啊。
举这个例子的目的是帮助大家理解这种呃在如何把它产生两个小的sub list,也就是小的子链表,然后这个怎么在一个列表后面接东西。因为我们接入的时候是接在列表后面的。
所以我们先把这个H1T1就表示小于X的那个列表的表头和表尾先是空,这个就体。😊,看了我刚才说的,如果不能保证链表里至少有一个元素,在接的时候会很复杂,就比那个刚才那个问题多写了很多代码。
H2和T2就是大于等于X的这个表头。那我们看一下。害的还是一步一步走。如果。headdY6小于X,我们要接到第一个列表上,这个就是接到第一个列表的过程。所以要判断一下,如果T一不是空。
T一就是那个第一个列表的表尾,如果它不是空的话,我就直接接上就行了。主要就是T一的nex等于headd,然后T一再等于headd就是T一永远指向表尾。😊,那问题在于,如果它是空的话。
那么第一个元素是一样的,表头和表尾都指向它。那这个大于等于X操作是类似的,也要判断T2是不是空,这个和这个T一是对称的。那退出来之后,我们想一下是什么东西。核出来之后,请注意这个T1和T2。
它的nex都没有负,因为T1的nex还是最后一个元素的nexT2的nex的还是hel nextex。所以这个T1和T2的nex的还是原来链表那些元素的nex,它们还没有动。
因为只有最后那个元素的nex没有动,所以我们要考虑这个nex怎么办?这里又要考虑两个链表,因为两个列表都可能为空。其实这里面如果T一为空,H11定为空。T2为空,H2也一定为空。
就是T一为空和T2为空和这个H1为空,H2为空是是这个同时成立的,就是同时判断的。那我们看一下,先看表尾,如果T2是空的话,那么就没有什么好说的了。如果T2不是空的话。
因为我们最终是要把这个H1这个列表和H2这个列表接起来。如果T2不是空的话,说明最终的这个表尾就是合并之后的那个表尾就是T2了。那么我们要把T2的nex的辅充空。😊,那否则的话就没什么好说的。
然后我们看一下,同样看一下T1,因为刚才说了T1的nex也没负值。那T1的nex它应该等于H2,这个就不用考虑H2是不是空,它是空,我正好让它等于空,它不是空。
我就把这个T1的列表表尾和H2就是第二个列表的表头接起来了。所以这一步做的是两个链表的连接工作。这一步做的是最终结果表尾的这个赋值工作。那最后返回了,其实应该返回H1,但是H1如果是空的话。
那就只能返回H2了。当然H2也是空呢,显然就是空了。H2不是空的话,我已经把这个呃就是H1不是空的话,我已经把这两个链表连起来了。所以这是返回值要注意,大家可以在纸上画一下这几种条件。
这个综合起来写出来,其实并不难。😊,所以今天六个例题都讲完了,主要涉及的还是链表的最基本的操作,做一些总结。首先链表的问题其实都不是很难。其实除了这个刚才讲的复制的那个问题以外。
都不是特别难写代码要细致。那怎么做到细致呢?其实还是要多写代码多练习。呃,写代码的时候要注意考虑哪些指针必须要修改。还有呢注意修改前修改这些指针前要保存这个后面的值,因为比方说单向链表。
你把前面的nex的改掉之后,后面元素就访问不掉了。所以这个会造成内存泄露,所以不能我们我们不能轻易让链表断掉,总总要保证后面的东西有变量值,所以这个要注意,还有就是注意很多特殊情况,就是空指针啊。
那些都需要判断。因为链表很讨厌的地方就在于这儿就是它很多空的情况和非空的情况处理不一样。对一个变量如果非空的话,我们可以取它的nex的啊,取这些东西。空的话我们什么都干不了。😊。
那电表的特点其实刚才也讲了,我们可以重新建立一个表头,把那些想要的值连上来。这个在翻转里面其实也这么做的。因为我们在翻转的时候,每次表头都是新的,每次表头都是当前这个节点。
把它连到就是把这个新的节点连上已经处理好的结果上。😊,那这个peition也刚才也已经讲了,就是最后那个例题,我们建立了两个表头,一个是小于X的,一个是大于等于X的。
所以列表的特点就是我们可以重新建立一个表头,把想要的东西一个给连过来。这个刚才已经说了很多次了,和数组不一样,数组需要耗费额外的空间。链表这个额外的空间是常数的那还要注意呢这个很多我们把列表拆开之后。
要注意呃第一个元素也就是表头就是sub list的表头和表尾非常重要。尤其是在表尾要接东西的时候,我们把表尾的nex要接上去,并且表尾要附成新接的那个元素。所以这些赋值啊,这些变量的变化非常重要。
多写代码就有感觉了。那另外一个其实对于指针的理解,其实我们经常就是在前面几个题。😊,经常说把把这个列表的地址,或者说把这个节点的地址放到set里面,或者放到map里面。刚才我也说了。
set和map并不是想放什么就放什么,必须有一个序的存在。但是放地址是没有问题的。因为地址其实它真的就是int值。😊,大概就这么几个总结吧,今天的课程就到这里,谢谢大家。😊。
人工智能—面试求职公开课(七月在线出品) - P9:探秘校招笔试面试 - 七月在线-julyedu - BV1Xf4y1r74s
。我的总体体会哈就是现在的这个笔试和面试的题目是越来越难了。并且这个他在除了考察这种编程语言、数据结构、数据库、操作系统、计算机网络。此外,这种此外哈,它还增加了好多像算法,像逻辑以及数学方面的题目。
而数学方面的题目呢,大家要尤其重视概率论这个方面的内容。呃概率论啊、数学统计这方面内容大家尤需要重视哈。然后呢,此外就是积极学习的题目,它做了一些增加难度呢也有一些。提升哈呃呃贝斯是属机济学习的内容。
我个人觉得哈,当是你再把它归类到数据归类到数据挖掘。一个意思哈,然后那个呃概率论这方面呢,可能更多的是考考察的就是咱呃大家在概率论和数统计那本这个一般大家的这个这个学习过程中。
那个大家本科生的教材或者营生教材哈,一般是这么个过程哈,就是概率论数学统计算是一门课,一块来跟大家交交涉哈。我一般是感觉是这样子。然后只不过这里面呢,可能在面试里面会大量充斥着一些关于算法和逻辑的题目。
大家有时候就会有些疑问哈,咱在以后的工作中,算法这种逻辑题真的会用吗?我觉得这个事情啊,咱们可以先唠叨两句哈。事实上呃算法题目分两两种。有一类的工种工作哈,真的会用到算法。
但是真的并不是所有的内容都需要它。但是呢尤其对于校招来讲的话,他没有一个更好的一个判断你能力的一个尺子来去度量。我应该是选择哪一些人,他总要筛一些人选一些他觉得合适的对吧?像这些基本内容以外的话。
他觉得考察算法是非常接近于我所想要的人才的对吧?他就会拿这个东西去呃,作为一个横量。另外呢就是说即使是突击学的算法,如果你学的还不错,就是通过了面试官和公司的考核的话,他觉得okK那这样的话。
你在学习其他内容的时候,应该也是一个非常好的一个苗子,对吧?所以说基于这个考虑哈,所以好多公司再去做呃,笔试面试题目的时候会增加算法题目,会增加逻辑题目。我想他的原因可能是这样子哈呃这个。
我只我个人的一个想法哈,大家看看是不是这么个东西哈。呃,这样呢咱就哦,对了,还有就是那个做广告了哈,就是呃大概在10月11号呃,每周六每周日下午的天到4点是我们的即将开始的10月算法班。然后呢这个。
还有一个9月机体学习班,它的时间是10月11号开始,每周六和每周日的晚上是9点到21点,就是晚上7点到晚上9点哈。就是说咱的9月算法班和10月算法班。
其实它的开始时间都是11月10月11号哈啊都是11月11号开始的。然后呃我大概罗列了一下这个它的算法班的这个。呃,大纲以及机学班。因为机学班有24课,那内容实在好多哈,然后我就随便截了一下后面的那几个。
然后大家有兴趣呢可以看一下哈。好了,这是关于呃报名的话,就直接呃我这儿一般右下角有一个主lyDU点com,这个是我们的官网。这个打开这个官网之后,就能看到它的报名链接呀,以及它的一些相关内容哈。
主赖APP点com呢是那个附属于官网之下的一个专门为呃手机app做那个一个做的链接哈。就在这里面大家可以发现知道我们的app有分安卓版跟那个IS版,大家可以在里面下载哈。呃,主要U点com。
大家打开这个就好了哈。里面有论坛,有这个社区论坛哈,然后还有一些课程,还有一些相关的内容哈。嗯,好了,这个我大概呢去贴了一下这个某一些公司今年的校招的一些题目哈。呃,咱随便看一个吧,比方说这个。
第一个为为例哈,比方说我们在这一个八行乘呃八列乘6行这么一个矩阵哈。然后我从A去移动到B的。过程之中一共有多少种不同的走法,要求是我只能够向上和向右来走,不能够走回头路,并且不能够经过P这个点。
就这种题目哈呃不算这种难度,我觉得应该算是中档吧。就是说不算难。但是呢我们还是需要稍微的考虑一下。像这些题目呢,咱等会儿会跟大家一个一个的去梳理,看一下它到底是怎么样去做哈。好了,呃。
你想有这种这种题目,我觉得其实是个算法题。而第二个做期望这个题目对吧?它其实是考上的概率论和数学统计方面的内容哈。而这个是一个典型的逻辑题目,需要在这里面,咱知道怎么样去推导推理,对吧?呃,这个题目呃。
你说它是算法也行,说它是推理也可以,对吧?就是说取这100个数,它们可能的绝对值的差的和,最大是多少。像这个题目显然是一个呃比较怪异的一个概率的题目。这个题目其实有一个。有一个更有趣的问题叫三门问题。
大家有兴趣呢可以去呃在我们的。那个7月份的app上或者是那个一些这个网站上去搜一下这个问题哈,都是一些很有趣的关于概率的,并且经常考的一些内容哈。这个是一个看起来像是一个推荐系统方面内容。
我们待会看看它到底里面想考察什么,其实没有那么的难哈呃这个呢我们就不再一个个的过了哈,然后我们只是跟大家看一下这个咱今天跟大家聊一些有关的题目哈,先看刚才的说那个所谓的推荐系统里面的一个小东西。
它是有先介绍一个背景哈,就是说呃商品推荐的这个场景哈。如果你是过分的去聚焦在这个商品推荐上,其实往往会损害到购物体验。有时候呢这个系统会选择一定程度的随机性来去给用户增加一些惊喜感,对吧?
惊喜度也是推荐系统需要考察的一个度量标一个一个呃一个标志哈。比如说我们假定在某一个推荐系统里面,想去计算A和B这两个商品,他们与当前访问用户的情况。假设说这个我用户来了。
并且他算出来了这个用户和A商品的匹配度是0。8和B商品的匹配度是0。2。这是我们经过其他的相应知识来算出来的哈。然后呢,我们系统呢随机的给这个A这个商品生成一个从0到0。8的均匀分布的一个得分。
给B这个商品生成一个从0到0。2的一个均匀分布的一个得分。然后呢,让你算一下。这个能够得到B的这个得分,本来是0。2嘛。那么说B的这个最终得分会大于A的最终得分的概率是多少?
大家先看把这个题目先读一下这个题目很长,但其实考察内容看起来像是推荐系统,但是向机器学习,对吧?但是呢它后面考察内容其实是让你算概率。呃,这个题目大家有嗯有感觉吗?怎么做呢?哦,卡卡说是条件概率。嗯。
那谁是条件呢?这种题目哈就是说哎糊的不亦乐乎,确实是糊了。非常好非常好。是这样哈,就是我们可以在这里面算面积就可以了。怎么算呢?因为咱这里面涉及的是A商品和B商品。人我们人类哈最习惯的是二维的一个东西。
而现在它给定的就是让算两个商品之间的东西,因为二元关系是很有趣的关系哈。当然,三元关系更有趣,对吧?然后A呢是从0到0。8的一个均匀分布。😊,B是1个0到0。2的均匀分布,因此我就画出横轴A和纵轴B来。
对吧?各自组成两个轴。A从0到0。8变化,B从0到0。2变化,因此它们总体的变化域就是从0到0。8和从0到0。2这么一个矩形,对吧?现在呢都是均匀分布的O这是这个二倍上也是矩上也是均匀分布的。
现在让我们算的是让B的概率大于A的概率,那很显然,画一条Y那个A等于B这么一条斜线,对吧?位于三角形的这个区域上这个这个点,比方说红色点在鼠标能看到吧,就鼠标假设在这个位置哈。
大家会发现这时候B它的值是这么高,对吧?如果鼠标在这儿的话,A是这么大,所以说这个B是大于A的嘛。所以三角形这块面积是满足B大于A这个情况的。一共满足条件就这么大,总共的是矩形面积。
OK算一下三角形面积,算下矩形面积一除就好了嘛,对吧?蓝色面积大算了下去,我算成0。02,矩形整个的是0。2乘0。80。16嘛,OK1除0。125。8分之1对吧?OK这个题目就做完了。有问题吗?哦。
那个。多谢捧场。😊,像这种题目哈,就是说呃往往遇到了这种算概率,并且是2元的事情的话,你其实直接画个面积一下子就出来了哈,没必要去真正的去去推导哈。你推导的话反而麻烦了,对吧?
我这里面呢为了让大家能够去理解这个事情哈,呃,咱再找一道。题目这个题目也是今年的一个实际的一个面试题哈,是这样子,大家思考一下,就是说假定AB两个国家元首。
他们相约在首都机场晚上8点到晚上12点之间去交换一个重要的文件。然后呢,如果这个AB两个国家的飞机哈,假设A国的这个飞机是先到的。okK那么A国的这个元首哈,它会等一个小时。
假设如果是B国的这个飞机先到的话,那么说B国这个元首会等待两个小时。现在呢我们假定这两架飞机,它们都是从20点到24点均匀降落在这个机场的,它的降落时间,它的分布是有均匀分布的。OK你算一下。
它最终能够在20点到24点完成这种文件交换的概率是多大。这里呢出一个呃就是加一个小tck,就是说我们假定交换文件本身是不需要时间的,就他们俩如果能碰面,okK就就算交换成功了。就这个题目哈。
这个题目呢我没有给大家给出解析。呃,大家可以思考一下怎么做。然后呢呃。就是那个咱的app上是有的哈,然后有兴趣呢,我可以把大家先想想。然后呢,咱在今天比方说假定咱的一个半小时之后结束的话哈,呃。
最后呢我把答案贴出来,好不好?😊,大家可以想想啊,都是一样的一个套路哈。这个题目比刚才那个题目呢难度要略高一点,略难一点点。就是它的画图呢要比它麻烦一点点哈。OK我刚诉大也是画图了。是吧。😊,哦。
就是那个电那个手机端好像是不行的,手机端好像只能听见声音,看不见APB看不见PPT的,只能是电脑端才行。好像是麦克是搞不定的,必须装虚拟机了哈。嗯。这个题目原题哈,它其实指的是在萧山机场。
ok大家知道是哪个哪个哪哪个公司的面试题了,是吧?是萧山机场,我记得应该是。嗯。约会问题,哪个约会问题?约会问题有好多好多是吧?好了哈,我们先呃就是mrZ先给个。😊,这个这个这个记记的解释啊。
咱后面看具体的后面的内容哈。我们来看第二道题目,是这样子,就是说我们给定一个公式是84乘148等于ECA8。如果是成立的话,那么说请问这个公式它采用的是几进制?OK是的,把刚才那个飞机换成人。
就是约会哈,没问题。嗯,OK这个第二这个问题哈,就是说如果它乘它等它的话,那么说这个公式成立的话,它是几进制了呢?这个题目应该怎么做呢?这种题目。事实上这种题目哈有一个放之四海而皆准的一个标准解法。
假定你是一个X进制的那这样的话,84就是8X加4,这个148就是1乘X平方,加上4乘X加8,对吧?BCA8,显然B是11,A是10嘛,对吧?这是10乘以X3次方,6乘以X平方。
10乘X8再加上这个8对吧?左边这个式子相乘等于右面这个式子OK你化简下就出来了,对吧?这个式子是不可能等于零的,因为X是大于零的一个整数嘛,然后这里面只有X等于12是可以的。这种做法是完全最标准的。
所以大家直接去呃遇到这种题目的时候,如果上来硬算,直接去这么算,一点问题都没有。对吧呃,第一个常规做法,大家看有问题吗?OK啊,刚才那个说到那个呃那个交换文件那个事情啊,就是概率论那本书上啊。
就是大家随便找一本概率论的书。呃,只要把那里边的古典概型问题搞清楚哈。一般来讲遇到面试题目呃,还是嗯。还是还是一般都能应对哈,起码是但是需要稍微的就是再把。往届的题目拿出来自己再练一遍。
那个清楚的去了解一下它的套路就好了哈。因为咱在学的过程中跟实际用的过程中它有一个台阶有一个差距。这个差距呢咱好多大学课程里面其实是缺失的。对吧咱需要把它补上就可以了。嗯。OK哈,好像是那个。
好像是那个就是征途中的人,那个好像是是是个是是个问题啊,是32分之19的,我我不觉得答案了,好像是这个。呃,这是第一个解法哈。第二个就是刚才STU爬虫说了,计算尾数就够了。是的,我们看一下。
如果启发式做法怎么做呢?事实上,如果在十进制体下来表述的话,左侧的这个是尾数是4,然后这个右侧的这个数是8,对吧?那4乘8其实48是32嘛,对吧?右侧这个个位数是8O这个32和这个八的差是24嘛,对吧?
那24的差既然是24,那这样的话,它的进制必然是24的一个约数,O这个里面只有12是24的约数嘛。对吧因为你这个24一定要是能够整除它的这个进制嘛,这肯定的对吧?他他他是。多了个零嘛,他一定是20。
只有C是20的对吧?这样子也可以搞定,对吧?然后这这种做好简单是吧?而呃我说明两点啊,就是说咱用十进制来做这个事情,仅仅是个技术习惯哈。另外就是说咱第二种做法可以作为第一种解法的一个辅助手段。
我们来相互交互验证一下,是不是做对了,对吧?这是跟人家说明的两点问题哈。OK这个题目有问题吗?嗯。OK那咱就继续下面的内容。继续了啊,没问题吧。😊,OK哈,就大家这个这个咱今天是一个公开课哈。
然大家记得轻松一点,这个有问题咱就问,然后没问题咱就过,咱就讲一些有趣的内容哈。😊,这个题目呢稍微的有点麻烦,就是它是一个N个数的差,我把它叫做这个题目的名字,我得起了个名哈。它是这样一个说法。
就是说我们从123到100这么100个数任意的去排列,形成一个环,或者是一个圈,一个任一个路,对吧?然后呢,我们要求的是求两个相邻数的差的绝对值求和最大是多少。当然有些的选选项,大家看看哪个答案是对吧?
首先这个题目本身没问题吧。从1到100连完做成个环OK后面数减前面那个数取绝对值,对吧?然后把这个绝对值加起来,哪个数那个这个绝对值的和最大能够达到哪个数能达到最大呢?对吧?能达到最大的是多少。
就就就这意思。这个题目本身没问题吧,题目的理解。就是我我一直是感觉,就是说咱做任何事情,先审题,题目想让他干上,咱搞清楚,对吧?然后我们再来考察后面如何去解这个题目。好的。
现在呢我们就来去琢磨下这个题目应该怎么做。我个人理解这个题目哈,用构造法是最合适的哦。blue eyes说了,用选E2500,是不是我们等会看看是不是哈。看一下哈。
他这里让我们算的是相邻两个数的差的绝对值。OK那这样的话。相邻两个数的差,这里从1到50,从51到100分两部分。然后呢,我把这个1到50叫小数,从51到100叫大数,这是这个是我个人的定义哈。
就是后面这个定义是完全我个人的,为了咱表示方便哈,咱就这么来说了哈,就是说把51到50叫小数,51到100叫大数然后呢,我们把这个相邻元素的差的绝对值好长一个东西啊,我们简称叫绝差之和。
这是绝对值差的和是吧?我呢叫绝差之和哈,造个名字。然后呢,我们看看怎么样去。呃,做这个事情哦,blue eyes这个想法没问题。先想想这里面它其实有一个问题是可以循环是吧?所以说这个你这个。
🤧结论哈稍微的再琢磨一下。现在呢我们来给定一个贪心的思路,就是为了让觉差之和起最大,我们就应该去先性的指导,要避免把大数跟大数放在一块,对吧?你俩大数放在一块儿的话,你抵消掉也好不好多不分嘛。
因此我就考虑怎么办呢?把大数和小数间隔着排。就是1234到50,后面跟着是各子跟着199,981到51懂可以吧,对吧?就是大数跟小数间隔着排OK事实上这个序列就是我想要的绝差之和最大的那个序列。
OK为什么呢?我们需要给出一个证明,对吧?那我就看一下怎么样去做这个事情呢。我们可以想想,OK我们如果说这个序列里面呃两个小数X和Y进行交换,或者是两个大数A和B进行交换,或者是大数和小数进行交换。
它都能得到一个我们想要的结论,或许就能搞定了,对吧?我们来看看怎么样去具体的来去想它呢。因为就这种三种情况,对吧?大的跟小的换大的小的跟小的换,大的跟大的换,除此以外,没别的情况。
我把所有情况都给你分析完不就完了吗?对吧?那这样的话我们看一下小数和小数换,假设用小数X小数Y来换O那这样的话小数X小数X的周围两个数一定是大数A和B,这个我假能记得XB哈,小数Y。
我记作它的周边周围两个数是C和D,对吧?这是我们的记号哈,那交换之前是长这样子的,交换之后,这个Y跑这儿了,X跑这了,对吧?交换之前的绝叉是X是A减X,B减X这个是C减Y,这是D减Y,对吧?
把这四个数加起来,就这个。交换之后呢,是A减YB减YC减XD减X,也就是这个数。大家会发现这两个数交换完之后觉差是一样的。对吧他觉他这个是一样嘛,都是ABCD减去2个X2个Y嘛。
ABCD减2个X减2Y嘛。所以说小数和小数换其实相当于没变。对吧。第二个。那大数和大数换呢就大数我记作A和B来交换啊,A两边我记住X和YD两边变成小数,因为我的构造方法是交叉的来做嘛,对吧?
这样的话B两边小数是Z和W记我知道记号哈。那么说交换之前就是这个。A减XA减Y,这是B减ZB减W交换之后的话,把B放到这儿,把A放到后面,对吧?那就是B减XB减Y。
这是A减ZA减WOK这两数一看还是相等。对吧然后第三个,如果我把大数小数A和大数Z做交换,小数A,我我这么写哈,它两边是XY是小数。然后这个大数是Z,这样的话,它两边是B和C,对吧?这样子的话。
大家会发现我如果交换之后的话,把Z放到这儿,把A放到这儿的话,你会发现绝叉交换之前是A减XA减Y这个B减ZC减Z,对吧?这是。交换之前的交换之后呢,发发现这是Z减XY减Z对吧?加距值值哈。
这个是A减BC减A加距值值,对吧?会发现这三个是大数凑在一起,这个是三个小数凑在一起,大家非常清楚能够把它证明出来,交换之后的话,它绝差,这个会变小。因为这里面它相互的抵消好的部分嘛。
这里面是大数跟小数讲减嘛,对吧?所以说你交换了。还不如不交换,你交换的话会导致你的觉差变小。而刚才这两种情况的话,你交换的话相当于没有任何效果,对吧?因此的话。
相当于我就证明了原始的这种状态是能够使得觉差之和最大的。对吧而这种原始这种状态,112099398这种情况,它的觉差是多少呢?后者减前者100减1是99。2减100或者100减2是98,这个是97。
这是909090减3,这是90。6对吧?然后51减50是1,然后一和51的差是50,对吧?而这个数我们加起来很方便得到。50就5000对吧?因为正好是。1到100加起5050嘛,就少了150嘛。
所以是5000啊,对吧?这是我们得到的结论本身。第二呢就是呃我们从刚才的这个小小交换和大大交换会知道哈,咱最终的这个觉差的这个最大序列不是唯一的。就是你可能构造一个这样的序列,它绝差之和是最大的。
我也可能构造一个别的,仍然是最大的。但是呢跑不出去,我通过小小和大大做交换,能够交换成跟你一样的。对吧。嗯。哦,我我加绝对值只是我因为我不知道这个X的Z谁大谁小,对吧?而这个这样的话,我我这写反了哈。
相当于这个我认为A大哈,AA大X小的话,就A减XA减Y了嘛。这这我这写反了,应该是大数A和小数Z哈,对吧?😊,因为我假定了这个红色的是大的,绿色是小的。对吧就是红的大绿的小。
OK你这样的话一减肯定你变小了,对吧?所以你交换还不如不交换。OK这是这个题目本身哈,我们看看大家有什么疑问吗?😊,就说呃刚才一朋友谈到了利用绝对值不等式的性质,其实就在这儿利用,对吧?
大家可以把它好认真可以算一下,对吧?如果是大家其实现性的一看就知道你这样会不会导致你的值变小,对吧?还不如这样放。嗯ん。如果某种排列不能根据你的排列器进行一步交换,得到的,怎么证明?他比你小呢。呃。
就是我我影证明什么呢?证明我这个序列,不管是大数跟大数交换,大数跟小数交换还是小数跟小数交换,它都不会得到更大的了。那显然这是最大的。因为我里面这个数我分成大数和小数两类,对吧?
然后我的交换可能性只有大大交换,小小交换跟大小交换,就这三种,我都证明了不可能。那不就得到结论了吗?我是这么一个想法哈。呃,OK这个题目嗯,那好。😊,这样。
数这样数围成圈和不围成圈直线排列情况的结果是一样的了。嗯。我没有好好思考过这个事情哈,我只是。看看哈,如果是。你要是不考虑他的话。少了这个减这个。感觉上可能不行,就是新媒朋友问的这个事情啊。
我觉得可能应该不对,应该不是哈。因为要是少了51和50的话,他那个。我感觉。但是我没有好好考虑哈,咱们可以好好想想这个。因为这里边会涉及这四个数价格不一样,对吧?我感觉是不对的对吧?是的。嗯。
我的意思是交换两次、三次、4次,而不是交换一次哦,你看哈我知道小小交换交换一次相等,你交换两次还是相等吗,交换三次还是相等的。你大大交换的,交换一次是相等的,交换两次也是相等的。并且你如果大小交换的话。
交换一次就小一点,交换一次就小一点。那这样的话,相当于你我就证明完了嘛。对吧。呃,两两减为什么要用一减51哦,它题目要求的语一朋友问这个事情啊,就是它题目要求的是这个围成一个圈。
让我算这个两个数的这个差值和哈。我这个序列是长这样子的,但51和1是相邻的所以就是用1减51做绝对值嘛,那就是50嘛,1减51加绝对值或者51减1一个意思嘛。如果有个新的序列通过两次交换得到。
第一次交换绝对值之和变小,但第二交换又变大,有没有可能超过对数的大小哦,不可能。因为我发现啊这三种可能交换方式要么就是相等,要么就是变小,不可能变大。对吧就是L。LIY同学问你那个事情哈。
因为这可能交换交换方式里面不可能有变大的情况。你看小小交换,它最后得到的还是那个交叉排列的情况。你看这是它变到这儿,它变成这,还是小大小大这种情况交叉排列的。大大牌的也是这样子的,对吧?
他还是这样的一个情况,这也是这样子的对吧?变成这个和这个他不可能再再变得更大了。嗯。这个怎么证明maxI从1到N?嗯。😊,令N加一等于1。令N加一等N加一等于一什么意思?嗯。是说的省略号是吧。
就是1到N加1什么意思?不是s加一等于一是吧,那那个那个那个后面那个。呃,就是这个题目哈,就是说呃。这个题目事实上通过这个方式,因为这个方法,我觉得就是就是构造法。咱们构造一个序列。
我看能不能通过交换的方式交换成为更大的。但事实上我突然发现第一次交换的东西就形成了一个更大的了,形成一个更大的就就就就就这就结束了。如果咱的题目里面会出现一个。我如果交换之后能够变得更大。
OK我一定交换过去。对吧我就能够交换更更好的事情。嗯。嗯。你比方说我突然想起来最小生成数,不管是perme算法还Ccard尔算法,对吧?咱不管是以边,每次添加一条边,还是以点,每次添加一个合适的点。
那个两个非常重的算法,prome算法。Cscard算法,这两个最小生成数,他们其实都是贪心算法,他们想法思路都是每次都选一个最合适的对吧?没错,就这个哈,然后呃其实思路是完全一致的。
都是先贪心的去搞一个东西出来。然后我最后证明不可能有别的思路能够比我这个贪心更好的情况,这就得到一个结论了哈。呃,所以我觉得这个题目本身呃是一个问题。另外呢就是说这个题目蕴含着的一些事情哈。
就是说如何去做思考,也是我们。需要更进一步的去去想的事情哈。嗯。OK这个题目能过了吗?O哈,刚才正好加了不少朋友进来哈,不知道能不能,那咱就正好从。呃,从这个题目开始吧。
因为正好是前面是一一个系列一个系列的嘛,一个题一个题的。所以说呃后面的题目跟前面的题目他们相关性很弱哈,有相关性的不大,后面会看到哈。呃,这个题目是一个非常非常经典的题目,经典到几乎任何一本书都会谈到。
是的。😊,是的,就是这个东西哈,我来看一下。😊,隔的血数或者叫走期盘这种东西哈,给定一M乘N的矩阵。然后呢,这个矩阵里面每一个位置都是一个非负的一个整数。
我这里面呢用一个彩色的值来表示它给定了一个非负的一个整数哈。呃,非负数也行,其用说这整数的意思是为了咱可以用int来支存它哈,你用fat,你用大爆其实跟那算法没关系。然后假定我在左上角放个机器人。
这个机器人呢每次只能够向右和向下来去走,不能够往回走。然后呢,他最终会走到右下角,对吧?那么说请问我从左上角走到右下角的话,这个经过的最小的那条路径是什么?对吧就是这个题目哈呃这个题目本身有没有问题?
😊,先把正把题目的审题验过了哈,题目有问题吗?题目的理解。好,行码没问题哈。有朋友谈到了大明朋友谈到了动态规划DP,然后HU朋友说到了组合排列,然后blue艾说是一个深度的呃优先搜索,对吧?呃。
深优先搜索有点过分了哈,因为那个时间缓了有点高,对吧?然后咱。有有时间咱给谈一些有趣的话题哈,填表法是个问题啊,是个事情哈了。呃,贪心和刚才那个动态规划,他们本质可以看的是一码事儿,对吧?我来看一下哦。
没必要用A星哈,呃,这个题目没没必要上A星A星的话,启发式的搜索,对吧?咱没必要上A星。如果是你要是算在那个。一个区域上,比如说在一个省份或者在一个全国这个范围里面求两个点之间最角路径的话。
你用A型算法应该是不错的哈。但这个题目没必要了。呃,就相当于是什么呢?相当于是你给你一个简单的一个,让你把一个鸡给杀了,你请了武松过来,没必要,对吧?就是请个柴进就就足够了哈,就这意思。呃。
O我们看这个题目怎么做的哈。O既然是它要从左上走到右下的,我们就来考察某一个点它的情况。首先我们知道哈在走的方向决定同一格子不能走两次的对吧?它是因为从左上到右下嘛。那么说它如果在红色这个点的时候。
那么说它可能是上一次来自于哪个格子呢?那很显然,他上一次要么来自上方这个绿色格子,要么来自于左侧这个绿色格子,除此以外,没有别的情况。对吧。我们就用1个DPXY来表示它如果位于XY这个点的时候。
它的最短路径。那么这样的话,这个DPX减1Y是它位于左边这个点,它的最短路径,对吧?那么。DPXY减一是指的它位于上面这个点,它的最长路径,对吧?那这样的话,这两个最长路径。
它们各自加上AXY就走到这个当前这个红色点,这两个值谁小,我就取谁就是能够走到红色这个点的最短的那个路径。对吧当然这个里面把这个公因式AX加Y可以提出去,对吧?得到这个式子,那咱变成好边嘛,对吧?
就是它两只谁小,我取谁,最后加上红色这个点就OK了。这个是普通的一个点上的事情。第二。😡,如果说假定它位于这个点呢,位于第一行呢,OK它如果位于第一行表如绿色这个点的这个位置。
它只能够从左到右依次去加上来。因此第一行的这个值就是前第一行的这些数的累加第一列的这个紫色,比方说这个棕色这个点哈,它是怎么过来呢?那只能是从上到下依次累加得到的对吧?所以第一行第一列我单独处理。
而中间的某一个点,然后我用一个最小值谁小我算谁的,加上去,最后就能得到又最后我去返回DPMN那个值就是。走到右下角的时候,它的最短路径的值是多少?对吧就是这个题目本身。
OK这个题目咱的解析就算是说说完了,有问题吗?呃,不知道有没有说清楚哈。😊,嗯,O会飞的鱼说了一下,贪心一定是最优的吗?贪心不一定是最优的,很显然,对吧?
这个题目里面如果是你我们更多的是把它说成是动动态规划,对吧?这个题目如果贪心的话呃,难说是吧?然后。嗯,贪心往往是能够得到一个还不错的解,但是一般而言不一定是最优的对吧?
但是呢贪心法其实是在积极学习里面用的更多,比方说咱去做梯度下降,咱就做梯度上升。呃,做为那个周标上升,本质都是贪心,对吧?因此梯度下降得到的是一个局部的优解。嗯ん。DP方程都写出来,肯定DP啊。
大家OK哈,就明白了。等我上O。O哈好的,这个题目,这是这个题目本身。下面呢我们来对这个题目做一点点的更进一步的分析哈。第一个就是如果这个题目里面把刚才我们说的,让你求最小路径。
从左上到右下这最小路径变成最大路径,大家会做吗?从最小变成最大。如果从最小变成最大的话,其实上面所有的分析过程就把里面的命变成max。所有的都不变,对吧?是的。
所以说这个题目相当于里面蕴含着两个对偶的问题,本质一样的对吧?我们就不再谈这个事情了,这是第一个事情。第二个,我们来继续分析它。呃,我们通过刚才的这个写法哈,其实可以呃不要着急。
这个咱今天呢谈一谈这个内容哈,呃难的题目呢呃今天准备的题目后面有有那么几个稍微难一点的哈。此外呢,其实还有一些呃需要做深度性搜索。然后才能够完成的内容。咱可以在后面的那个有机会的时候。
咱跟大家继续去聊哈。呃,这里呢其实大家千万别重要重视这个事情哈。就是什么呢?咱通过刚才的这个写法,其实非常方便能写出更漂亮更规则化的状态转移方程,对吧?第I行第零列对吧?
也就是呃第零列这个东西或者第零行这个东西都能写出来,对吧?这是第。嗯。第零列的对吧?这个是第零行的对吧?然后这个是任何一个点的对吧?此外大家其实可以发现哈,这里边咱可以使用动态滚动数组的方式来去降为。
因为如果你这么写状态转移方程的话,其实你的空间复杂度是M乘N的OM乘N对吧?但是如果你这么写的话,把这个DI这个第一个维度扔掉的话,一行一行的去滚动的话。
其实我的状态我的呃空间复杂度就能降到O mean就是类似于这么写法。就类似于这个说法,对吧?是M和N的最小值。前面是个大O对吧?这么个东西哈,所以空间反能够从。大体上从N方降到了N,是这个意思哈。
然后我把代码呢跟大家做了一下,这个代码其实是降维之后用滚动数阻来写的。大家可以参考一下哈,就是这边其实给随随机给定了一个棋盘,然后我怎么样去求最长路径,然后我先去初始化,初始化这个其实就是这个东西。
然后呢,这一块就是谁想我取谁,然后只是做了一个这个滚动数组哈,最后我返回第N个值就好了。这是呃这个它的那个相关代码,大家可以看一下,那个有兴趣,因为笔试嘛笔试面试里面有时候不光考你算法。
还需要考你实践啊这一部分基本功我们需要把它打扎实哈。好了,那课件的话,我们等会儿放到群里好了哈,对吧?然后课件没问题啊,这这个咱把它下载了就好了哈。😊,这个一点问题没有哈。嗯。
然后呢这个题目我们继续去挖掘它。其实这个题目就是我刚才咱刚才说到的,为什么有些公司他去面试的时候会考你算法呢?不是说算法在实践当中没用,这个题目就有用。虽然看起来这个题目很简单。
就因为刚才有的朋友说讲那么简单的问题,我们觉得不爽,对吧?但是事实上如果给大家出个别的问题呢,这个题目经常跟大家分享哈。假定我们空间中有两条曲线。
这个蓝色的这个其实是一个绿色这个点组成是个空间的一个曲线啊,它是记得拐弯的空间给定的。然后呢,如果给你空间两条曲线的话。让你实际里面去连出一个曲面来。要求是什么呢?
要求是这个曲面去经过给定的这两条线的控制点,这是第一个要求。第二个要求就是生成的起面最好看。就是两个要求哈,其实硬象就是第一个。第二要求就是你时间你发挥了。这个题目是我在实际里面。
实际这工作里面这个项目上需要做的一个内容哈,也是一个我们这个软件里面,就是我自己开发的一个软件啊,就是说呃算是号称比较核心的一个一个算法。最难的就是什么叫好看?对吧什么叫好看呢?我是这么定义的。
就是说如果我给你的一个曲面,它总有一些连接线,对吧?中间会生成一些这个连接线嘛,就白色这个线,对吧?我定义,如果这个连接线的加和是最短的,我就认为我生成这个曲面是最好看的。
我把这个东西起个名字叫做能量最低,我认为能量最低越低越稳定,就可以吧。对吧我就这么这么这么说了,OK我就以这个为我的目标函数做事情。怎么做呢?事实上这个做法非常简单。就是因为左这是一条线,这是一条线。
那么说左边这个线假定有M个值,右边这个线假定有N个值。那么说第零个点可以和这第N个值各自求距离。第二个点各自求距离,第三个点各自求距离。因此在我眼中给定的这两条线,其实是一个二维表格M乘N的。
他让我做什么呢?让我做的是从这个二维表格的左上点,从零号到0号的这个这个线连接起来,一直连到DM行和DN列的这个连起来。最后形成的这个路径的总和最小。它对应的就是我这个曲面最好看。对吧。因此。
并且这个里面跟这个题目完全对应的,因为它不可能走回头路的,一旦走回头路,这个曲面就自相交了,对吧?自相交,自己和自己相交了,不可能。因此我就利用刚才那个代码,只不过加上咱实践里面的一些这个。
这个这个这个项目相关的一些一些内容把它生成出来,最后得到就是这样一个曲面。我把这个曲线呢把它加密了一下,OK得到也是这样一的东西。这个这个代码已经是经过实践的有效检验的话,应该实际里面效果还是不错的。
这个就是大家分享的一个有趣的一个话题哈,就是如果给只给你道题目的话。你会发现其实很难,但是呢它背后隐藏着那个算法,好简单是吧?就是一个二维棋盘左格子的问题。事实上这个题目我可以把它做的更漂亮一些。
就是说如果给定了这个两条线,不是这种这种折线,而是。而是两个封闭的环,我就会生成一个柱状的体。如果给定了一个是一个环,另外是两个环的话,我会生成一个带分支的一个区别。
如果说我在给定一个上面一个曲面,下面一个曲面,我中间会得到一个曲面,对吧?我就能生成一个企。我甚至于要求生成的这个曲面。我最开始生成这个蓝色曲面哈,这是绿色曲面,我经过用户画了一些引导线。
我必须经过这个引导线的话,会得到粉色的这个曲面。而这些都是咱在刚才所得到的这个二维表格的时候,强制经过某个点,就是经过一个这个引导线嘛,强制经过某个点,只是对刚才这个算法做一点点补丁就够了,对吧?
大家有兴趣可以思考一下相关的问题哈。
OK这块有问题吗?
这是咱跟大家分享的这个题目哈。😊,呃,有问题吗?大家给个反馈。呃,因为他跟实践相关了。对吧。嗯,我感觉是这样啊,就是说其实。嗯,就是就是什么呢?就是说大家最基本的哈,就是说先了解这块。
就是说这个算法很很简单,对吧?刚才我讲到这块,大家反应还是很正常的。就是告告诉我是这块懂了没懂,我们有些交流,讲到后面这块大家懵有点懵是吧?但是其实无所谓,对吧?
就是一些算法在实践中的简单的一个应用而已,对吧?因为我本身是记得出身哈,做计算几核出身的。
所以我可能觉得就习惯了哈,那是大家稍微简单思考思考就是了。而我说的我稍微加一点内容哈,大家不妨再思考一个问题。空间中给定一条折线,然后呢我让你在这个折线上加一些点,加密它形成一个更光滑的曲线出来。
大家知道怎么算吗?这个其实是我们在呃。也是一个正常的一个算法哈。事实上他要求的一般而言是要求的二阶导连续。其实这里面隐藏着一个这个算法本身要比连曲面不简单的。
这个有有幸大家可以看可可以琢磨一下这个问题哈,怎么样给定你的一些空间点,我让它光滑出来得条更好的线。嗯,OK我们看看大家的问题哈。😊,是的哈,就是二维映射哈。嗯。滚动数阻那里是什么意思?
即使连线的需求是什么?没听明白哦,滚动数阻这是仅仅是一个做的降维。就是说呃本来这是个二维的。如果你做这个编程的话,大家这样吧,就说这个代码是我仅用了ON的时间复杂度去实现的空间复杂度哈。
然后大家如果用简单的这个直接版本的这个转转方程,其实是OM乘N的空空间复杂度,大家可以把这个实现一遍,再跟这个对比一下,就能够知道这个滚动数阻到底面是什么东西了。大家不妨把这个思考一下哈。
其实这里面虽然算法本身并不难。但是里面把所有的细节都搞清楚,我觉得才能够算这种题完全掌握了哈。就是你可以对任何人去阐述这个事情。不管是面试里面,还是在工作讨论里面哈。第二。
G41连线的要要求就是说给定了空间两条曲线,然后呢,你生成一个曲面,要求的是曲面呢能够过这个原始的这些两条线,并且生成这个曲面最好看。因为其实呃生成的过程不是这这一种,还有别的连接情况。
但是呢别的情况呢,我定义做没有我这个好看。因为我说我这个能量最低。我刚才一坨东西哈。就这个的就是我的应用就是这样子的,相当于是什么呢?相当于我比方说大家想想它的应用是什么呢?
就是说比方说假定我们做CD扫描。就CT扫描得到脑成像的两个距离很近的两个面。我现在需要把这个脑这个这个脑的这个三维形状给它给反衍出来。其实就是这个算法哈。嗯。二连续是光顺的。呃,这个咱就不讲了哈。
就是说这里面其实呃用二调导连续是最有,其实是有其实是合适的一个东西哈。知道了就是跟实践相关的,也就应该就知道道底它硬在哪了,是吧?Okay。好了,这是关于这个事情哈。😊,呃,不是导数连续,是二阶导连续。
就是导数的导数是连续的。如果是导一级导数延续的话。
光顺性不是那么的强。然后我们继续去考察这个事情哈,这个题目还没有完。我们现在呢假定用DPXY来去表示,如果位于XY这个点的时候,它一共有多少种可行的路径。比如说有红色点的时候,XY它有多少可行路径。
那么说显然DPXY就是DPX减1Y和DPXY减1,它们两个的可行路径加和,对吧?这个是我们刚才已经得到了一个结论,马上就能写出这个方程了。现在呢我们看一下这个方程是长这个样子的对吧?
我们现在可以怎么做呢?就是把这个X加Y多一个维度。写到这来,这个X减1YX减1加Y多一个维度,这个X加Y减一多维度写到这来,这种可以把?我加个维度总可以吧。第二呢,我再把最后这个Y这维度给它删了。
不要了,就变成了这个X加Y,这是X,这个X加Y减一,这是X减1,对吧?把Y扔了哈,这个是X加Y减一,这个是X把Y给扔了,对吧?这种可以吧?然后我令这里边的X加Y等于T写的好看一点,这是TX。
这是T减1X减1,这是T减1X对吧?我把这个呢写成这样一个记号CTXC减1X减1,这是CT减1X,对吧?然后呢,我令里面的T是NX是M就得到这样一个式。对吧。这个式子就是大家非常熟悉的组合数的公式。
没错吧。符合数公式,我们就可以通过刚才的动态规划的这个式子来去得到它。没错吧,所以说这个呢也是刚才咱的这个格子取数走期盘这个问题所蕴含着的一个非常重要的公式。因此,刚才因为有朋友谈到排列组合吗?
所以说我们可以说它真的是一个排列组合相关的题目。对吧。😡,好了,我们继续哈呃,咱才进行了一半儿。😊,呃,就是后面的哈就说我个人认为呃大家一般而言这个题目哈,有些你们会谈到这个或者就结束了。
有些地方可能谈到功能数组结束了。有些时候呢一般而言不会谈到这个,这个是我自己相关的。另外呢这个是我就是简单的一推就得到这个式子了,对吧?好了,这个题目呢我们。呃,在哪看?哦,这个。这个是我自己的总结。
那那那个没有一个具是是什么东西啊。然后呃另外呢就是说呃主要那本书里应该是会谈到一些东西哈,就主来那个不是新出一本书嘛,然后他马上就要上市了嘛。嗯。然后就是这个题目,我们把它再琢磨一点东西,就是变成例4。
1的意思哈。哦,在哪听课听课就是我就这个主来EDU点com。就来,我敲一下。就这个这个里面已经是我们官网哈,里面有一些东西可以大家看一下。然后有些课程那个或者是大家自己看公开课也好,或者是报名也好。
那个随意哈,大家看什么都行这个。学东西为为为为主要嘛。然后呢,这个咱把这个题目再来琢磨一下,就是说还是我们给定一个这个棋盘。这个棋盘呢它是一个八列六行的对吧?1234566行对吧?我们把它转过来哈。
就说从A点让它去移动到B点。只能够向左向右走和向上走,只能够走到这个B。要求是不能走回头路。第二,不能经过点P。那么说这样子一共有多少种可行的走法呢?当然,如果没有这个不经过批这个要求的话。
横着1234567。纵着12345对吧?C10。呃,127或者C1251个意思哈,对吧?我能求出来一个值,就是刚才咱推出来这个结论嘛,对吧?事实上这里面呃如果不经过P的话,怎么做呢?很显然哈啊。
这个是咱这次的一个面试题哈,就是笔试题哈,这个题目本身是个笔试题。今年刚刚刚刚出来。怎么做呢?就是我从A到B一共需要往右走7步,往上走5步,因此可行走法C125。但是从A到P呢,对吧?向右走5步。
向上走三步就到P了,因此是C85这么多走法。而P到B呢向右走两步,向上走两步,对吧?C426种走法O这个那么从A到P是56,从P到B是6,因此,从A到B经过P有多少种呢?56乘以6嘛?
这不是一个乘法原理嘛?对吧?得到336种,而一共多少种呢?792种,792减336就是456。这个就是刚才这道题呢答案,从A到B,一共需要456种。哦,有问题吗?ok哈。
这些东西都是咱在那个就是那个7月算法app那个7月算法APP7月算法app那个里面得到的一些一些内容哈。嗯,只是咱今天时间稍微的宽裕一点,所以我就把这个题目展开,从走期盘,从各种各样的有意义的东西。
然后去把它给。聊出来哈。另外呢就是咱可以根据刚才我们的说法,其实如果是这一共有一种,这一共有一种,每一个就这么写就完了嘛。比方说这个十怎么得来的,有左边这个值,下面这个值加起来70怎么得来的。
左边这个值下面这个值加起来,只不过这个值P点的值是0。然后比方说98怎么得到70加28嘛,我们总能把它算出来也是这个数。对吧如果大家不想这么算,并且你非常的任性的话,你可以这么玩一下,对吧?
其实答案肯定是一样的。对吧。好了,这个就是关于走期盘类似的一个非常长的一个解析了哈,有问题吗?是不是DP就是排列组合呢?呃,这个显然不是哈,对吧?因为这个DP哈它其实。老祖宗把它叫做这个玩意儿。
对吧或者叫阳灰三角,或者叫甲线三角甲线三角,对吧?它其实本质上咱给定的是一个2乘2的,其实这个呃是矩形的,而这个三角那个给定的是一个金字塔型的本质一样哈,对吧?哦,对对。
7月题库app哈7月题库APP哈。因为。就是就是怎么说呢?就是咱我不知道是说他。吹一下就是失大招风也好,还是什么样也好啊。就是说如果你大家直接在里面打上契月算法的话。
会大家会发现其他的一些广告就是不是我们的。但是别人会把这个搜索引搜索词给他给买了,然后呢就说是7月算,那不是啊,那不是我们。就说我们的那个官网。就这个主来一丢点com哈,然后。呃,这是这这是没问题的哈。
然后7月提库APP是我们的7月提库app是我们的这个名字哈,那个app的名字哈。嗯,里面总是会有各种各样的事情发生哈,我们不谈非技术啊,因为咱就聊技术本身O这个题目有问题吗?还。😊,好。
然后呢我们下面呢呃可能。今天呃分享的内容有点多了哈,再跟大家再多聊一会儿哈。大家如果有就是时间如果不够的,大家就先。各哥哥妈各家这各着哥妈了,对不对?😊,这个题目是这样子的。
就是说我们把这个题目叫做寻找程序员。我们现在有ABCD4个人。然后呢,这四个人呢去应聘一个成序员的职位。这个职务的要求是什么呢?就是说我们要求要java熟练,要懂数据库,要会外部,此外还需要有C加加。
并且谁满足的条件越多,ABCD这4个人就雇佣谁。并且我们先艳性的知道这个这四个要求哈,就是java数据库外和C加这4种。然后呢要求的是呃。两个四个里面两两组合,每两个组合恰好有一个人是满足的。Wow。
😮,全球直播。那就不能瞎说了,是吧?然后两两组合里面恰好有一个是满足的,并且我们知道了一些知识,就是A和B是java熟B和C是会外部C和D是懂数据库。D呢有C加加经验。
但是其他的比方说那个A是不是懂外部不知道。然后呢,你现在通过这四个已知的条件,以及联能组合,只有一人满足。你最后推一下ABCD各自会哪些技能,并且最后告诉我他我们应该雇佣谁。啊,是的。
这个题目就是瓦特和blue eyes说的没问题哈,就说这个题目语言这是。实际面试的时候出的一道题目,我呢把它变成了那种表述方式,就是情种那个题目哈,我把它贴了一下,等会儿。
然后咱先把这个题目本身技术层面先解决清楚哈。这个题目怎么做呢?我是推荐我我个人的这个解法是这样子哈,我们来看一下。🤧首先达标。把这个信息整理出来,就是A会java。
B会java跟外部C会数据库跟外部D会数据库给C加加,对吧?这是条件告诉我们的对吧?然后把人和物列成表格里面,把各子会什么打上空格处是未知的,对吧?并且他告诉我们两两组合只有一人满足。
这里面只有4种技能,4种技能,C4我四种技能里面两种组合,对吧?一共就这6种情况,对吧?java数据库java外部java C数据库外部数据库C和外部C就这6种,对吧?那这样的话,这6种组合。
我把它命名作甲乙丙丁物集这么6个条件,它呢恰好只有一人满足,并且我知道java跟外部,他告诉我了,对吧?java和外部是B满足的数据库跟外部是C满足的然后数据库和C加加是D满足的。
但是外部和C加加java跟C和java和数据库不知道得待定,这是我们所有信息没有丢,也没有创建新的我们的假定对吧?我们先把题目做一个整理,这是我们得到的原始信息。下在我们都对这个信息进行我们的推理。
这是第一步。对吧。😊,第二步。我们来分析这个条件组合。比如说我举个例子吧,我这个图的意思哈,比方说我们以这个为例哈,有以这个比方说。A这个人能不能会外部呢?假定他会外部的话。
别忘了这个里面jama跟webB已经会了,对吧?java跟外bB是会的。那么如果A也会外部的话,他就和甲这个条件发生矛盾。因此我打了个错叉号,并且我注意一下它是跟甲这个条件发生矛盾的这个意思哈。
比方说这个B能不能会数据库呢?我们知道数据库和外部C已经会了,对吧?数据库外部C已经会了嘛。如果B再会的这个数据库的话,那么说。他必会数据库这个事实就和乙这个条件发生矛盾,我就我打个叉号。
因为它是乙矛盾的对吧?这是我是这么来做的哈。另外呃其他的分析。比方说A能不能会数据库呢?A如果会数据库,大家会找里面A和数据库,它的情况是待定的,我们不知道它是真还是假,因此。
空格的这个东西是未知的未知的,不要做任何假定,把它空着。因此我们每个都分析出来之后,有些完全可以把它给确定出来,一定是假,有些待定对吧?这是我们经过刚才的第一步整理信息。
第二步我们分析这个信息得到的第一次信息的一个提升。有问题吗?😡,是的哈呃我这里面大概就是把呃BAT嘛,这里面的一些题目主要我讲找的都是阿里的,有一些其他题目哈,然后跟大家做一个分析原题哈这是。😊,嗯。
mrZ说-931094106,这是什么东西?我们继续哈,然后我们得到第一步,对吧?就是得到这样一个表格了。OK我们继续。现在我们就来一点点思考哈。😊,我们看一下这里面。🤧。因为这里面哈这个we部。
这一列里面会发现,大家先看这个好了哈,这个里面java这一列数据库这一列和C加这一列都有空白发生。而外部这一列啊,我们都拿到信息了。因此,外部这一列我们是完全确定的,谁会谁不会。
因此我们就重点关注一下外部它这个条件呃,有什么事情发生哈。比方说这里面外部相关的这个外部数据库已经知道了。而外部C加加不确定,我们看一下外部C加加。那这样的话,外部它只有B和C去掌握。
因此外部C加加只能在这二人B和C之中产生。并且这个C我们已经知道它不会C加加了。对吧因此这个C加加必然只能是由B来会,才能够满足丁这个条件,对吧?
这就是通过这个为什么我们能能够去得到这个外部C加加这个把它给强制出来,是因为我们刚才分析的数据完成了这一列,它是我们最确定的对吧?然后我们就可以知道外部跟C加加这一列B只能会C它必然是B会C加加的对吧?
既然B会了呃C加加。因此哈C加加和java这一这个这个它俩选项,对吧?C加加和java这个选项,这个物这个选项也只能由B来掌握了。对吧因为他会的仨了,已经对吧?并且我们知道他不会这个数据库了,对吧?
这里面呢这个呃D它能不能会这个java呢?D如果会java的话,java和这个C加加这一项本来是必掌握的对吧?它如果也D如果会java了,java跟C加加,它就跟这个条件物发生矛盾了。
因此D不能会java,这个空白处应该打叉,对吧?那我们再看这个那么说这个A能够会C加加吗?A如果会C加加的话,那么说呃A也会了java也会了C加加,它也和这个条件物发生矛盾,对吧?
所以说A也不能会C加加,这个必须打叉,对吧?而A能会数据库吗?A必须会数据库,因为同时会java和数据库的,还没有人存在呢,这都是叉号啊,所以说A这块应该打勾。所以说我们就把这三个又确定下来了,对吧?
是这样一个情况。很显然,这里面B会了这三种,而ACD各会两种。因此我们应该去雇佣B。OK这个题目有问题吗?嗯。我觉得其实这个分析应该算是最正的,就是说嗯。没有多费气力的了,对吧?就是画这个表格。
并且我告诉了大家,我们怎么样去利用这些信息。对吧。嗯。重么来去做这个事情哈,就是说咱先怎么做再怎么做,一步一步的做出来就好了哈,我觉得是最合理的。其实。因为没错啊,就是mr熏猫说的这个事情啊。
就是说咱讲肯定是慢的哈。呃,事实上呢这个题目我在微博里面去把它更新的时是这么说的。对吧我把ABCD叫做李逵、宝玉、西门和呃纳兰。然后呢,我把这四个技能把它叫做西施貂蝉呃,昭君和玉环。然后呢。
我我我就把它把它写到这儿了,对吧?其实一样的对吧?并且我说任意两个美人,只有一个才子,喜欢他们俩。最后你让你说谁是喜欢的人最多的,我就认为谁是情种,对吧?题目是完全一样的哈,对吧?OK呃。
这个题目可以过了吗?😊,嗯,小倩是不是又学会一招?好了,我们现在呢这个看一下这个题目哈,后面的题目呢就是有很简单的一个东西了哈,呃不要着急,我大概还需要也就是十0分钟吧,就跟大家来探讨完了哈。
大家稍微的再陪我聊一会儿哈。就是这么个内容啊,就是说现在我们有一叠纸币,其中5元的面值呢是有6张,然后10元面值的有5张,20元面值有4张。现在呢要求从这些纸币里面任意的取4张。
让你去算一下每种面值至少取一张的概率是多少。就这个题目啊,这个题目本身并不难哈,我把这个东西都把它叫做古典概型。古典概率模型,遇到这种题目,直接做两件事情。第一个就是算基本事件是什么。
第二个算有效事件是什么?显然这里面一共有6张、5章、4章,一共15章,对吧?15章里面任起4章的所有题法是基本事件。然后满足歧义的就是要求至少一种的概率,这是我们满足其的有效事件的。取法对吧?
基本实间15章里取4张是什么呢?是C154,对吧?这题干5的又列了一遍,因为咱这样大家看得清楚哈,654章各自取4张要求的是至少有一个。有时件是什么呢?就是让这个从5元10元2元里面要求至少有一个。
是取两张,其他取一张,这才能够满足的要求嘛,对吧?那这样的话,比方说咱从这个6张里取两张,剩下的5张,4张各取一个,从5张内取两张,6张4张内取各取两各取一个和4张内取两张,然后呢,6张5张内取一个。
对吧?这就是把它加起来。然后这个就是我们的这个有效时间的数目,有效时间数目除以我们基本时间数目,就是我们最终得到的概率。是的,就是说排列组合其实是我们中学就学的对吧?
只不过呢咱在概率论那门课程里面只是跟大家告诉了,咱再算古典概型,直接就去算基本事件数目多少个,主要剩有多少个,然后一出就得到,不要去想过多的事情。就是大家如果是只是去不是按照这种思路。
不是按照这种套路去做事情,而是就是遇到这个题目捣鼓捣鼓,遇到题目捣鼓捣鼓。嗯,不系统啊,就是我我所觉得就是说我们之所以会跟大家去探讨算法这门课继续学习这门课,是把。
我们个人对于这个内容的一些套路性的东西哈,跟大家做一个这个分享。因为这个是比这个题目本身要重要的多,对吧?就是把它套路都学对,每一个题目,每一个类型,每一个情况都有各自的一个东西发生哈。对吧。是的。
也可以算无效事件多少个。然后算完之后呃,无效事件的概率,然后算完多少,用一减去它也是可以的啊,完全一样的东西。嗯,没没没有问题哈。但这个题目如果是算对立面的话,好像算的。无效事件可能比他还要略多。
你可以试试哈,我记得好像是这样子的,所以就没有那么算。就是易鹏说那个事情啊,好像是要反而更多了。OK这个题目有问题吗?就这么简单吧。这个题目出它是因为这个题目本身是这次的一个面试题一个笔试题。
另外呢就是呃这个题目其实蕴含着咱可以算这个题目。我看一下哈,这个题目怎么算,这个题目稍微的就麻烦一点了哈。从123到99,一共99个数字,外加2015,构成了100个数,对吧?从这100个数里面。
我任意的去选择一部分数出来,当然选了这个一份数可能是零个,也可能是最多100个,对吧?都有可能。然后呢选出这部分数来以后呢,我让你把这些数各全球易获,获得的个新数,对吧?
像当我选了一份数来求异获得的一个数。那么说求的这个数,它是一个随着我怎么选,它会得到一个不同的数。因此这是一个呃随机的事件。OK我就能求这个随机这个事件X它的期望。请问这个期望会是几呢?这是这个题目。
我们先看一下这个题目有问题吗?呃,瓦特说有效事件能这么算吗?嗯,好,654。嗯。是不是不行啊,我没有好好考虑哈,瓦特那个说法。会不会有重复?因为呃这种这种这种把一个词混进去的话,往往会重复哈。
我没有自己考虑法特那个那个那个解法,C61乘C51那个那个那个那个乘起来哈,我没有好好考虑,我我。就是无脑型的不思考,我觉得可能不行啊,但是我没有任何。这个这个进一步的思考方式哈哦。咱可以探讨一下。
因为时间有点拖了有点长了,我就就不不再探讨这个事情了哈。等会儿我们可以在私下来,我们再来讨论这个事情哈。嗯ん。O哈,大家还在沉浸在刚才这个里面,是不是?我们先把这个题目搞定如何?OK我了解了。
其实大家其实对于这种。这种更直观的题目还是更有趣的哈。如果涉及难题的话,大家就就累了,其实是不是?呃,我们先把目光放在利七上,如何?呃,就是大家先看这个题目哈。
那么这个题目先看的就是咱先继续把这个题目先搞定哈。就是这个题目就是。呃,先看这个题目本身有没有问题。好的,然后我们来分析这个题目会发生什么。这个题目就需要利用刚才我们说的国内概型。
所以不要小看国内概型那种简单题哈,它会用到我们的难题上。首先我们知道哈针对任何一个二进制位取奇数个一,如果异或的话,它就是一偶数个一异或的话,就是零一和一异或那就是零,对吧?那偶数个嘛,它异或为零。
这是异或的特点,并且和取多少个零是无关的,只和一的个数有关。对吧而这给定的这100个数里面,2015显然是最大的。2015把换成二进制是长这样子的,它呢一共有11位OK既然有11位。
我就一位一位的分别考虑,假定我现在考虑到了DI位,就是我记得大XI假定我要算DI位,它的期望哈,我们来怎么看呢?让他能算它的概率。OK我们就算一下这个大XI这个值等于一的概率有多大。
并且我们假定这个里面给定的这些数里面第I位。第I位哈就是你不给了我100个数嘛,1234999掉2015嘛,这里面一共有N个1M个0,这种可以吧,我假定了哈。
然后我们在里面假定某一次采样得到的一的个数是K个。对吧这是我们把它得得得定义出来,要不然没法写公式。怎么算呢?显然它要等于一的话,相当于我在这里面先得到有M个0,对吧?M0随便取对吧?但是一不能随便取。
一的话必须取奇数个一。对吧奇数个一在这儿,对吧?因为我们刚才说了,奇数个一才可以从CN里面取奇数个一有多少个,而偶零呢无所谓,就是可取可不取,一共有2的MM次方个,因为N个0嘛。而一共有多种取法呢?
一共有N加M个位,因此二的M加N次一共有这么多位,对吧?这个公式的写出其实就是古典概型那套东西。大家会发现难了吧,就是说呃你说这不就是高中知识嘛,对吧?但是高中知识也也很有用啊,对吧?咱把它用到这儿。
对吧?这是有基本实,这是底下那个是基本事件,上面这个是我们有效事件。有效事件对应的是等于一的值嘛,一用多少这么多个O这样的话,这个二的M和这个2的M消掉了,就变成二的N次方,对吧?而这里面这是CNK啊。
K是取奇数,别忘了,咱高中学过组合数奇数项各的加和,偶数项各的价和,它们值是相等的,因此,奇数个这些值相加除以二的N次方,恰好等于2分之1。对吧所以说这个概率是个定值2分之1,跟NMK都没关系。
对吧这个是我们这道题目的最核心的一个公式。搞定他这个题目就走完了90%了。有问题吗?哦,有朋友老是说掉线,呃,那个我的声音有时候会过不去,是吗?哦好哦,那就是。呃,可能咱全国各地哈,有些朋友网络可能是。
OO有断断续续的地方是吧?啊,不管了哈,总之。这个对吧?其实这这个公式写出来,它蕴含的内容特别多,对吧?有古典概型的,有咱高中学过的知识,然后最后得到2分之1了。O我们继续现在我们算的是第I位的情况。
一共有11位是吧?O那么11位的这个二进制里面每一位取一的期望都是2分之1,对吧?那么说最后这个X的期望是什么呢?X期望就是I从一位到11位,这个XI取值乘以XI等于一XI的这个取值的概率,对吧?
而这里面XI呢可以取一可以取零,取零的话,这个值是零取一的话是二的X次方嘛,对吧?这个是我们基本的概率论的公式,对吧?得到它这个零扔了不要了,就是它而这个等于一的概率这块。
其实就是我们刚刚算出来的那个2分之1,对吧?而别忘了这个里面是。这若干个数,这是11个数的求期望,就等于这11个数各自求期望再加起来。因为我们有一个非常重要的公式,X加Y的期望等于各自期望的加和。
并且这里X和Y可以不相关,那可以相关,可以不独立。都有这样一个结论发生,对吧?这个我们在积极学习里面会跟大家再一次谈讨这个事情啊,很重要的一个公式。对吧我们在集水里面也会。经常会用到这个东西,对吧?
然后呃20分钟足矣2分钟足矣哈,然后这个得到它对吧?得到它以后的话,其实会发现它是2分之1,这是二的I次方,对吧?一乘OK这是分之1提出来,这是I从1到112的I方加加起来,这个数不就是12嘛,对吧?
这个数是几啊,10。呃,这是201就是2047,对吧?2048减1嘛,2047除以21023。5。对吧所以这个答案就是这个数。就F。好了,这个题目我觉得是一个相对而言不简单的内容哈,大家有兴趣。
这家我觉得需要引起重视。这里面又探讨了一些有趣的话题,并且跟积器学习的内容有关,跟上海有关系哈。另外呢最后呢是我们探讨一个简单的一个题目哈,就是说呃我们快速过一下时间复杂度的一个问题哈。
就是说呃假定我们有个函数my funk,它的时间复杂度是O一的。那么说这段代码的时间复杂度是多少呢?I从一到N,I每次都去乘3,然后J从I出三开始,J到一结束,然后调用my funk这个函数。
那么说这个的时间复杂度是多少呢?哎,这个题目不难是吧?这也是今年的一个面试题啊,但应该不是阿里的,应该是。嗯,准一线的一个公司哈,这是个准一线的公司。曾经是一0行。呃,当然我这里多了个小柱哈。
就是说呃其实我们用那个西塔来表示啊,大西塔来表示的时候,表示是紧的。就是咱们的堆排序里面建堆时间复杂度是西塔N,不是西塔N乘logN哈。当然我们说呃大ONlogN是没问题的。因为大O的我记号。
咱要求的是这个不要求是确解,但是西塔要求是确解哈。这个题目的话,如果让你求确解的时候,它是讲不到多少呢?简来看一下啊。这个里面的内层循环,它是从I从这个呃不好歉思,写错了,这是这是外层循环。
就是外面那一层哈,这个I给定一个I。啊,抱歉,真的是那种情况。这个G从3分之I到I,因此它其实内存循环循环次数是3分之2倍的I。而Y层里面呢I从一到N去做变化,每次变成3倍。也就是13927这么变。
通项显示是三的K次方嘛,对吧?这个显示三的K次方,最终是要小于这个N的。我们认为这个这个这个这个小N嘛,对这个小A是要求的嘛。然后呃K呢是从012到到某个数嘛,三的K的方小于N就好了,不管K等于几。
你可以写出来写成K等于log以三为底N的对数等等等等东西哈。那咱不管了。然后呢呃内层循环次数每次按照递增3倍做累加。怎么做呢?显然一的话用3分之2乘以13的话。
3分之2乘以33分之2乘以93分之2乘27,一直到3分之2乘以3的K次方K次幂,对吧?这个就是我们最终的时间,它的关于N的一个次一个一个变化,把3分之2提出来就这个数嘛,这个数候我们利用高中知识。
这是一个公比是三,首项是一的一个等比数列,对吧?那么说它的前N项和就是前K项前K项和,对吧?是这个数化简一下,是这个东西,三的K次幂减3分之1,显然别忘了三的K次幂小于N呢,对吧?它接近于N。
但是它小于N,然后这个数候显然小于N的对吧?因此这个时间复杂度,它的。上节也好,下节也好,都是ON。对吧它其实是一个线性的。OK这个题目有问题吗?好,然后呢事实上画个图要更清晰哈。
因为每次这是从I从3分之I跳到II又跳到3I3I跳到9I,对吧?如果等于I的时候,是从3分之I到I紫色这一部分。如果是从3I的时候,是从3I除3,就从I开始到3I部分。因此。不管怎么样。
它前面是紫第一次走紫色的,到红色又走红色的,到9I,从3I到9I,每次都是把这个加起来,因此它正好是整个的线段长度是吧?所以说在线段图上能看出来它的时间复杂度真的是1个ON的。
对吧大家可以这么一画就简单了哈。😊,好了,这个呢就是咱跟大家聊的一些讲的一些内容哈。这里面呢我给出了三个思考题,一个是猜数字的题目。第二个是还是咱刚才说的那个三门问题的一个升级版本,就是猜全。
然后翻了一半,然后做事情哈,三个就是笔试事件,设箭的话,然后一个人设101件,一个人设100件。那么说假设中的次数比乙次数多的概率是多少?这个题目我在微博上也分享过,对吧?然后我用的是析施和。
貂蝉那个例子来做的例子,回头那个那个例子哈,一个意思的话,对吧?呃,这些东西呢其实在我们的那个APP上都会有那个。解析哈,最后呢做一点点小的总结哈。呃我觉得就是咱要两点,第一个重视思想。
第二个一定要重视我们的动手的能力。我个人这点想法哈,就是说因为首先我们计算机科学,它是一个实践学科。你至少要掌握一门能够精通的一个编程语言,你要落地啊,对吧?第二就是提高内涵,提高你的内涵之后呢。
能够赢起所有的不管是你的竞赛还是你的比赛还是你的这个面试笔试还是以后的工作。任何一个对战平台都是一个终极法宝,对吧?另外呢就是一定要重视咱教科书上的基本的内容。这些东西是我们这些东西。第一这是基础。
有了这些基础。然后呢通过把这些基础能够把它融汇贯通连成网络,形知识网络,就能够得到更进一步的知识。比如刚才我们谈到的那个呃就是走期盘问题,对吧?我觉得内涵就是算法算一方面,我个人觉得哈。就是。
这个东西对吧?然后我所感觉到的是什么呢?就是说嗯。咱的那个大学教育里面哈,其实每一个学科都是非常重要,非常好的。但是呢它缺乏了一个各个学科之间的一个融会贯通一个交流。
你能够利用各个学科的知识把它给做一个事情出来。对吧所以呃这个我觉得或多或少大学教育有点缺失。所以正好就给了我们企业算法一个契机哈。我觉得所以在这里面可以做一点点事情里面呃。分享一点个人的心得哈。
比方说让你自己实现一个快速排序,读bug了。大家问几个问题,广州优先搜索或者叫宽度优线搜索对吧?用什么辅助设置结构,还记得吗?对吧?然后字符全排列,你知道怎么样设计一个算法吗?怎么样设计一个代码实现吗?
OK如果这个字符串是有重复了,有什么事发生的?如果这个字符串我们递归去做,有什么可以怎么做?如果非递归做又可以怎么做呢?另外我问一个问题,字符串的全排列可以用在什么地方呢?对吧我没有写出来啊。
但是也很重要,全盘列可以用在哪儿,用在实践里面的哪些东西。为什么非要做全盘列这种看似很无聊的一个题目,对吧?它其实都是很有趣的一些内容哈。好了,这个呢就是跟大家分享的一些内容哈。
别忘了这个首先题目是来自网络哈,然后做个感谢。另外呢解析呢有7月提供的APP7月提供的app。然后呢,这是安卓的这是IOS的这个二维码哈,大家可以扫一下,然后下载。然后里面的解析呢是我们自己做的内容。
然后看看。如果是大家发现有些问题,我们可以探讨,大家麻烦大家告诉我。如果是做错了,或者是哪儿有不严格的地方,我们来把它给呃做的更完善一点哈。呃,停几秒主赖。主亮要扫二维码是吗?OK我们停一下哈。呃。
那主亮,你扫好了之后,告那个告诉一下哈。😊,就是。安卓版本和那个IS版本的那个二维码的部分哈啊PPT没问题。PPT的话马上跟大家就分享就好了哈,这个一点问题没有哈。啊,多谢多谢多谢。呃,因为有些东西。
有些东西还需要跟大家这个。嗯,做交流哈,因为这个其实分享的越多,然后呢自己的提高也是更多的。其实我是这种想法哈,所以还是。所以我是。OK大家算好了吗?哦,多谢多谢。呃,另外呢就是我做一个小广告啊。
就是非常希望大家能够这个。这个这个这个拍一些照片发给我们哈嗯。这个。呃,虽然看脸的时代啊,但是我觉得。反正我我是想多看两眼的,我不管大家是什么情况哈。😊,不会的不会的,这个嗯。不会的肯定不会。
这个大家肯定是很很什么的哈。OK这个我们的官网主来U点com,然后呢跟那个也july的微博,然后企业题库的和企业算法的微博以及微信啊,大有都放在这里了。大家这个可以这个。跟我们做互动啊。呃。
然后别忘了就是10月的算法班和9月积极学习班哈,我们定在了10月11号,因为前面要放假,11放假哈,所以说只能定到10月11号来上课了。后面就是周六周日,然后一周双课去上课了哈。
这个最会跟大家再聊一聊这个事情哈。好了,那今天呢咱就把内容跟大家做了一个简单的一个分享一个内容哈。嗯。报名的话,我记得应该是三人组队或者是发微博加微信的话,应该是8折。
具体的大家看那个主lyDU点com那个官网哈,因为我实在是不知道这个报名费是多少。呃,就是主ly搞一下这个事情哈,就是有多少报名费的事情哈。OK那我记我今天任务就完成了。
跟大家聊要记住本身主了还需要说话吗?上一张PPT。是这个吗?两个班都报的话。OK好,那你主要不说那,咱今天的那个分享的话题就跟大家那个暂时的聊到这儿哈嗯。这个美女是我们呃。O我我说一下。
这是我们上海这样的一个新象大使哈,大家有兴趣可以做各个。我们非常希望各个城市都有我们自己的这个想大师哈。OK今天我们先到这儿哈,然后呢,我们这个嗯。😊,有机会我们再跟大家去交流更多的内容哈。好好好好。
谢谢大家哈,今天咱先到这。😊。