面试总结之-查找算法分析
2013-05-17 10:51
337 查看
先说明一下~这里的查找主要指二分,不指DFS,BFS(那些我后面放到搜索部分)。
查找的分析
关于查找,最最最重要的是二分查找,也是这系列所有博客中最重要的部分,除了二分查找之外,还有平衡树,但是不会让你写平衡树= =!一般就是对于STL中set,map的使用,STL的东西一般也不会一定要你用,但是如果面试时什么都自己现场写的话肯定来不及,也容易出错,记住几个常用的数据结构的接口还是比较重要的,不懂的可以上去这里看看:http://www.cplusplus.com/reference/stl/,主要的是set,
map, deque, list, vector, stack。
先是最简单的二分查找,二话不说先上代码。
Code[0]:
这是一个一般的BinarySearch:找到target就返回下标,找不到就返回-1,代码简单易懂,注意while循环条件有个等于号(不然你会漏了元素没有判断);但是考这个的可能性并不是很高,因为太简单了,一般会是一些变种,比如:找出大于等于target的最小值,小于等于target的最大值,大于target的最小值,小于target的最大值 = =!(绕晕了),不要急,后面一个个分析,据我所知,面试时要写前面几种二分,还很多人会写错边界条件的。
一个例子就是:给定一个有序数组,问数字大小在[a,b]区间的有多少个。这个做法就是找出大于等于a的最小值的下标i,找出小于等于b的最大值下表j,返回j-i+1。如果问数字大小在区间(a,b),那上面找的值就没有“等于”了。
这四种二分看起来很麻烦,其实就是在一个框架下进行一点点改变就ok了。首先先给一个二分的框架:找大于等于target的最小下标。
Code[1]:
跟上面标准的二分来比,这里不在循环里面return了,放到了循环外面return一个i。注意这个框架,有两个地方可以进行修改,分别对应上面讲到的四种二分要求:
1. if(tar<=a[mid]) VS if(tar<a[mid])
2. return i VS return j
从1,2中各选一个可以对应上面的某个二分要求,比如上面代码,用了if(tar<=a[mid])和return i,就对应“找大于等于target的最小下标”。当然这个东西是不用死记的,想想某个数组,包含有多个target,比如0 1 2 3 3 3 4 5 6,你要找大于等于3的最小下标,那当a[mid]等于3时,你自然应该搜索左半部分(如果你搜索右半部分,得到的3的下标将不是最小下标),最后结束时,i,j分别应该指向 2和3,i>j,所以应该要返回i。如果不能取等号,就应该返回j。总结一下就是:
这个表,记下来是没用的,在脑子里面跑一下二分的过程自然就明白什么情况应该用哪种二分,想象数组中有多个等于target的值。
最后这个程序在找不到符合要求的数字时返回的下标是溢出的,如果返回了小的坐标(j),溢出情况是返回值为-1,如果是返回大的坐标(i),溢出情况的返回值是n。
如果觉得理解了,可以上去做做这个题,直接就是上面提到的二分的两种,点进去,不要回头查代码,一次AC吧:
Search for a Range
这题也基本一样,你可以认为简单点(其实就是一样的):
Search Insert Position
接下来就是平衡树了。平衡树(具体说是红黑树)在STL里面的应用就是set和map(还有multiset和multimap),这东西做的事情跟二分查找差不多:用O(logn)的时间查找某个数或者查找不超过阈值的某个最大(最小)值,这些操作都跟上面的几种二分查找一一对应。但是平衡树的优势在于它是可以动态插入删除数据的(这个你用数组就不行了),缺点在于面试时你是没办法自己写一个平衡树的(要是面试官让你写个红黑树,你就把他吊起来打吧)。一个例子是:从数组中找和最接近给定值target的连续子数组(数组有负)。可以这样做:求出sum数组,对于sum[i],从[i+1,n-1]中查找一个最接近sum[i]+target的值,查找方法是,sum存到一个multiset里面(平衡树),每次i+1之后,把sum[i+1]从multiset中清除。时空复杂度O(nlogn)+O(n)。
关于红黑树(或者其他平衡树)的介绍可以看看这个文章:教你透彻了解红黑树
你只需要大概知道红黑树怎么个旋转法就好了,除非你自己感兴趣,不然不需要知道具体怎么代码实现,在面试时纸上写个红黑树太灭绝人性了。平衡树没什么好说的,主要因为面试不用写代码,只需要知道STL怎么用就好了。而怎么用STL就不说了,easy job,自己进去文章开头的那个连接看看自然就懂。上面给的两个题,当然你也可以用STL的set来坐坐看(杀鸡焉用牛刀~~),另外再给leetcode上面几道关于二分的题(不一定只能二分,但二分是一个可以接受的解):
Divide Two Integers 二分答案~
Median of Two Sorted Arrays 这个题个人觉得很不好做,大家要是有什么特别浅显又不容易错的方法,请贡献个代码吧
Search in Rotated Sorted Array 这个貌似是面试高频题,不难搞,思考清楚边界条件,一次AC吧
Sqrt(x) 这个题本身不难(尤其告诉你怎么做之后),不过它有一个把输入输出换成double的版本,思路一样,但是有一个很陷阱貌似很多人前赴后继的跳进去了,而且这个陷阱是不归路~~~
Search in Rotated Sorted Array II 这题放上来坑爹的,做做就知道怎么坑
其实讲起平衡树,总是跟哈希有千丝万缕关系,不过由于哈希太重要了,后面另起一篇讲了。他们之间的关系,看看STL里面,那些平衡树版本的数据结构时不时就蹦出一个哈希版本的(map 跟 hash_map)。最后加一句就是,红黑树跟有序数组这种差别(前面提到的动态和静态),在很多数据结构里面都体现了,比如预处理成数组的RMQ和线段树维护的RMQ,一般来说,面试时如果只需要静态的,你就写静态的,因为动态的不好写,然后也许面试官有个follow
up问你动态怎么办,那你就聊聊动态的,尽量避免写代码了(虽然线段树比红黑树好写。。。。。)
查找的分析
关于查找,最最最重要的是二分查找,也是这系列所有博客中最重要的部分,除了二分查找之外,还有平衡树,但是不会让你写平衡树= =!一般就是对于STL中set,map的使用,STL的东西一般也不会一定要你用,但是如果面试时什么都自己现场写的话肯定来不及,也容易出错,记住几个常用的数据结构的接口还是比较重要的,不懂的可以上去这里看看:http://www.cplusplus.com/reference/stl/,主要的是set,
map, deque, list, vector, stack。
先是最简单的二分查找,二话不说先上代码。
Code[0]:
int BinarySearch(int* a,int n,inttar){ //n是最后一个下标,tar是要找的数 int i = 0, j = n; while(i<=j){ int mid = i + (j-i)/2; if(a[mid] == tar) return mid; if(a[mid] > tar) j = mid-1; else i = mid+1; } return -1; }
这是一个一般的BinarySearch:找到target就返回下标,找不到就返回-1,代码简单易懂,注意while循环条件有个等于号(不然你会漏了元素没有判断);但是考这个的可能性并不是很高,因为太简单了,一般会是一些变种,比如:找出大于等于target的最小值,小于等于target的最大值,大于target的最小值,小于target的最大值 = =!(绕晕了),不要急,后面一个个分析,据我所知,面试时要写前面几种二分,还很多人会写错边界条件的。
一个例子就是:给定一个有序数组,问数字大小在[a,b]区间的有多少个。这个做法就是找出大于等于a的最小值的下标i,找出小于等于b的最大值下表j,返回j-i+1。如果问数字大小在区间(a,b),那上面找的值就没有“等于”了。
这四种二分看起来很麻烦,其实就是在一个框架下进行一点点改变就ok了。首先先给一个二分的框架:找大于等于target的最小下标。
Code[1]:
int BinarySearch(int* a,int n,inttar){ int i = 0, j = n; while(i<=j){ int mid = i + (j-i)/2; if(tar<=a[mid]) //等于往左走 j = mid-1; else i = mid+1; } return i; //返回i(i比j大) }
跟上面标准的二分来比,这里不在循环里面return了,放到了循环外面return一个i。注意这个框架,有两个地方可以进行修改,分别对应上面讲到的四种二分要求:
1. if(tar<=a[mid]) VS if(tar<a[mid])
2. return i VS return j
从1,2中各选一个可以对应上面的某个二分要求,比如上面代码,用了if(tar<=a[mid])和return i,就对应“找大于等于target的最小下标”。当然这个东西是不用死记的,想想某个数组,包含有多个target,比如0 1 2 3 3 3 4 5 6,你要找大于等于3的最小下标,那当a[mid]等于3时,你自然应该搜索左半部分(如果你搜索右半部分,得到的3的下标将不是最小下标),最后结束时,i,j分别应该指向 2和3,i>j,所以应该要返回i。如果不能取等号,就应该返回j。总结一下就是:
二分查找总结-jiacongxu | ||
等于target往右搜 ( if(tar<=a[mid]) ) | 等于target往左搜 ( if(tar<a[mid]) ) | |
返回小的坐标( return j ) | 小于等于tar的最大值 | 小于tar的最大值 |
返回大的坐标( return i ) | 大于target的最小值 | 大于等于tar的最小值 |
最后这个程序在找不到符合要求的数字时返回的下标是溢出的,如果返回了小的坐标(j),溢出情况是返回值为-1,如果是返回大的坐标(i),溢出情况的返回值是n。
如果觉得理解了,可以上去做做这个题,直接就是上面提到的二分的两种,点进去,不要回头查代码,一次AC吧:
Search for a Range
这题也基本一样,你可以认为简单点(其实就是一样的):
Search Insert Position
接下来就是平衡树了。平衡树(具体说是红黑树)在STL里面的应用就是set和map(还有multiset和multimap),这东西做的事情跟二分查找差不多:用O(logn)的时间查找某个数或者查找不超过阈值的某个最大(最小)值,这些操作都跟上面的几种二分查找一一对应。但是平衡树的优势在于它是可以动态插入删除数据的(这个你用数组就不行了),缺点在于面试时你是没办法自己写一个平衡树的(要是面试官让你写个红黑树,你就把他吊起来打吧)。一个例子是:从数组中找和最接近给定值target的连续子数组(数组有负)。可以这样做:求出sum数组,对于sum[i],从[i+1,n-1]中查找一个最接近sum[i]+target的值,查找方法是,sum存到一个multiset里面(平衡树),每次i+1之后,把sum[i+1]从multiset中清除。时空复杂度O(nlogn)+O(n)。
关于红黑树(或者其他平衡树)的介绍可以看看这个文章:教你透彻了解红黑树
你只需要大概知道红黑树怎么个旋转法就好了,除非你自己感兴趣,不然不需要知道具体怎么代码实现,在面试时纸上写个红黑树太灭绝人性了。平衡树没什么好说的,主要因为面试不用写代码,只需要知道STL怎么用就好了。而怎么用STL就不说了,easy job,自己进去文章开头的那个连接看看自然就懂。上面给的两个题,当然你也可以用STL的set来坐坐看(杀鸡焉用牛刀~~),另外再给leetcode上面几道关于二分的题(不一定只能二分,但二分是一个可以接受的解):
Divide Two Integers 二分答案~
Median of Two Sorted Arrays 这个题个人觉得很不好做,大家要是有什么特别浅显又不容易错的方法,请贡献个代码吧
Search in Rotated Sorted Array 这个貌似是面试高频题,不难搞,思考清楚边界条件,一次AC吧
Sqrt(x) 这个题本身不难(尤其告诉你怎么做之后),不过它有一个把输入输出换成double的版本,思路一样,但是有一个很陷阱貌似很多人前赴后继的跳进去了,而且这个陷阱是不归路~~~
Search in Rotated Sorted Array II 这题放上来坑爹的,做做就知道怎么坑
其实讲起平衡树,总是跟哈希有千丝万缕关系,不过由于哈希太重要了,后面另起一篇讲了。他们之间的关系,看看STL里面,那些平衡树版本的数据结构时不时就蹦出一个哈希版本的(map 跟 hash_map)。最后加一句就是,红黑树跟有序数组这种差别(前面提到的动态和静态),在很多数据结构里面都体现了,比如预处理成数组的RMQ和线段树维护的RMQ,一般来说,面试时如果只需要静态的,你就写静态的,因为动态的不好写,然后也许面试官有个follow
up问你动态怎么办,那你就聊聊动态的,尽量避免写代码了(虽然线段树比红黑树好写。。。。。)
相关文章推荐
- 面试总结之-查找算法分析
- python算法分析---查找和排序总结
- 常见密码算法总结--(4)加密模式的openssl代码分析之cfb模式
- 微软面试、经典算法、编程艺术、红黑树4大系列总结
- 加密解密算法总结分析
- 微软等数据结构+算法面试100题(16)--查找子串
- AdaBoost中利用Haar特征进行人脸识别算法分析与总结1——Haar特征与积分图
- 算法(第四版) 学习总结三 抽象数据类型、算法分析_待补充
- 机器学习总结(lecture 5)算法:Fisher线性判别分析LDA
- 计算机专业找工作面试面经总结(操作系统,数据库,数据结构,算法,虚拟化,编程实践等)
- 冒泡排序、选择排序、堆排序、快速排序、插入排序算法复杂度分析与算法实现(自己总结与转)
- 机器学习常见算法个人总结(面试用)
- 算法分析(总结)排序算法性能及比较总结
- 算法面试总结
- AdaBoost中利用Haar特征进行人脸识别算法分析与总结(转载)
- 算法分析与设计课程总结
- 面试总结与分析(一)
- 前端面试中常见的算法问题总结
- 开源复杂网络分析软件中社团发现算法总结
- July大神关于面试中算法学习的总结