电话面试算法问答记录
问:一个数组,先递增后递减,要返回最大的一个数,怎么实现?
答:依次遍历第i个数,如果第i个数大于第i + 1个数,那么返回第i个数,这个数就是最大值。(这么简单,大一学生都会)
问:还能优化吗?
答:啊。。。。。。
(比o(n)时间复杂度还快的算法就是o(logn),那应该就是二分法,关键是怎么判断一个数是否是最大的那个数观察数组,1 2 3 4 5 4 3,如果如果第i个数小于第i + 1个数,那么说明第i个数在递增那部分,最大数在后半部分,我们缩小一半范围再去后半部分找最大数,如果第i个数大于第i + 1个数那么他有可能就是最大数,也有可能在递减那部分,如果在递减那部分,说明最大数在前半部分,我们缩小一半范围再去前半部分找最大数。但是如何判断是否就是最大数呢?那就再增加一个判断条件。我们看第i个数,第i - 1个数,第i + 1个数三个数的规律。如果三个数依次递增,那么第i个数就在递增部分,如果三个数依次递减,那么第i个数就在递减部分,如果三个数依次先增后减,那么第i个数就是最大数。)
使用二分法查找,设中间数下表为i,如果第i个数大于第i - 1个数并且第i + 1个数大于第i个数,那么第i个数处于递增序列部分,使用后半部分数组继续进行查找;如果第i个数小于第i - 1个数且第i + 1个数大于第i个数,那么第i个数处于递减序列部分,使用前半部分数组继续进行查找;如果第i个数大于第i - 1个数并且第i个数大于第i + 1个数,那么这个数就是最大数。
问:时间复杂度多少?
答:logn。
问:你笔试那道三数之和题(给一个无序数组和一个目标值,判断数组中能否找到三个数,使三个数之和为目标值)怎么做的,时间复杂度多少?
答:那个用了HashMap将数组的数key = 值,value = 值第下表方式全部存储进去,然后用一个二重循环,一层i循环一层j循环,判断HashMap中是否含有(目标值 - 第i个数 - 第j个数)。时间复杂度是o(n^2)。
问:还有别的方法吗?
答:啊。。。。。。
(对于一个无序数组,先快排成一个有序数组,时间复杂度为o(nlogn),然后定义三个指针i,j,k初始别为0,如果第i个数 + 第j个数 + 第k个数小于目标数,那么就k++,如果第i个数 + 第j个数 + 第k个数大于目标数,那么再将k++就没有意义了,那么就去去移动j,不对,这么做时间复杂度还是n^3,无非是在做剪枝工作。再想想。
对于一个固定的i,如果初始化j 和 k为一个接近的值,那么就可以更快了。有了,固定i为0,设j为1,k为最大下标值n - 1,如果第i个数 + 第j个数 + 第k个数大于目标值,那么就将j++,如果第i个数 + 第j个数 + 第k个数小于目标值,那么就将k--,当k == j时跳出循环
将i++再次进行判断)。
设三个指针i = 0;j = i + 1;k = n - 1;固定i,对于寻找第二个数和第三个数使用双指针方式,如果三个指针对应数之和小于目标数,就将j指针向后移动一位,如果三个指针对应数之和大于目标数,就讲k指针向前移动一位。如果j == k。那么就跳出循环,将i++,接着进行判断。这样时间复杂度为o(n^2)。
问:还有别的方法吗?
答:(面试官你别太过分!)想不到了。
总结
算法题其实大体方法比较固定,比如说关于数组部分,可以用HashMap,二分法,双指针等方法优化时间复杂度。但是并不是单纯的靠你会不会这些方法,而是考察你能否在这些方法的基础上根据题目要求进行略微修改,比如说第一个算法题,他用到了二分法,但是
判断条件和缩小后半部分和缩小前半部分要根据题目要求自己思考。
再比如如给一个有序数组和一个目标值,返回数组中大于目标值的最小数用二分法,也是对二分法的改变。
第二道算法题用到了双指针,但是是在一层循环里使用双指针查找。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。