面试中遇到了一些算法,下面就来介绍一下这个算法.
1.阶梯算法
有一个n阶的阶梯,你每一次要么走两步,要么走一步,问有几种走法。
我们先列出某种走法,如下。
1 2 1 1 2 ..... 1 2 1
也有可能是
1 2 1 1 2 ..... 1 1 2
我们发现一个规律,其实最后一个数字要么是1,要么是2.这个时候,我们豁然开朗。
假设f(n)表示n阶阶梯的走法,那么必定有
f(n) = f(n-1) + f(n-2)
这样,我们就得到了这个算法。
从计算机的角度,我们需要怎么计算这个n呢,其实可以列一个n个长度的数组,把f(i)(i为1到n的任意数字)记录下来,我们就可以通过0(n)的时间复杂度得到答案了。
细心的朋友会发现,其实这是一个数列的表达式。对了,这其实就是斐波那契数列,具体怎么计算这个数列,百度一下吧。下面贴一个网友给的答案。
f(n) = (1/√5)*{[(1+√5)/2]^n - [(1-√5)/2]^n
这时,我们就可以通过0(1)的时间复杂度去计算了。
2.查询数字
有一组有序的数字,比如1,3 5,6,8,13,18,20。从中间某一段(不知道的某一段)分开并把后面的接到前面去,比如变成13,18,20,1,3,5,6,8。现在给你一个数k,要求在这个数组中找到k所在的位置。
这个看上去很像一个二分查找,但二分查找的基本条件是数组有序。这时候该怎么办?
第一种方法,0(n)的时间复杂度,挨个找,很显然不是好方法。
第二种方法,变种的二分查找。时间复杂度是o(logn)
其实,我们应该发现这个数组第一个元素肯定比最后一个元素大,而且第一个元素和最后一个元素最中间的元素大小一定不会在前两个元素之间。设mid = f((n-1)/2)我们记作(mid<=f(0)&&mid<=f(n-1)) || (mid>=f(0)&&mid>=f(n-1))一定成立。
对于任意的f((n-1)/2),我们会发现以下几种情况:
第一:(mid<=f(0)&&mid<=f(n-1)) 且k <= mid,那么k肯定在0到(n-1)/2之间,继续本变种二分查找。
第二:(mid<=f(0)&&mid<=f(n-1)) 且k >= mid,那么k肯定在(n-1)/2到n-1之间,这时候,你会发现,(n-1)/2到n-1之间的数字其实是有序数组,我们只需要利用平常的二分查找即可。
第三:(mid>=f(0)&&mid>=f(n-1)) 且k <= mid,那么k肯定在0到(n-1)/2之间,,这时候,你会发现,0到(n-1)/2之间的数字其实是有序数组,我们只需要利用平常的二分查找即可。
第四:(mid>=f(0)&&mid>=f(n-1)) 且k >= mid,那么k肯定在(n-1)/2到n-1之间,,继续本变种二分查找。
算法完毕