面试常见算法总结

这里是我在网上搜索的一些面试常见算法,总结一下,利人利己。

top k 问题:

选取第k大(前k大)的数可以采用类似于快速排序的方法, 利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。时间复杂度近似为O(n)

也可以用最大堆的方法,pop k次即可。

海量数据的top k 问题:

比如在一亿(N)个数中选取最大的10000(m)个,这时候要分情况讨论,如果说内存不足的话,那么可以采用建立一个m最小堆,然后遍历N个数,如果大于堆顶则插入。

如果内存足够的情况,可以直接采用快速排序方法,可以借助分治法,比如把N个数分为100份数,分别找出100个最大的10000,然后最后在100万中找10000个最大的。

选取频率最高问题

海量数据的top k 问题,如果有1g大小的文件,需要统计其中出现频率最高的100个词,有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。

方案:顺序读文件中,对于每个词x,取hash(x)%5000,然后按照该值存到5000个小文件(记为x0,x1,…x4999)中。这样每个文件大概是200k左右。

如果其中的有的文件超过了1M大小,还可以按照类似的方法继续往下分,直到分解得到的小文件的大小都不超过1M。
对每个小文件,统计每个文件中出现的词以及相应的频率(可以采用trie树/hash_map等),并取出出现频率最大的100个词(可以用含100个结点的最小堆),并把100个词及相应的频率存入文件,这样又得到了5000个文件。下一步就是把这5000个文件进行归并(类似与归并排序)的过程了。

海量数据处理–http://blog.csdn.net/yangquanhui1991/article/details/52172768

通常就是先hash映射到不同的小文件中,然后通过hash map求频率,最后归并

两个有序数列的中位数:http://blog.csdn.net/zcsylj/article/details/6802062 采取二分法的思路

有一个数组,设其为N1,如何取出前N2大个数,数字都是0-10000之间的 。 可以用基数排序,时间复杂度为o(n)

1.数组中逆序对计算。(剑指offer)
2.判读一个树是不是另一个树的子树(剑指offer)
3.数据流要求o(1)求得中位数,o(lgn)插入(剑指offer)
4.顺时针打印矩阵(剑指offer)
5.复杂链表复制(剑指offer)
6.二叉排序树中第k小的数(剑指offer)
7.反转链表递归 、非递归(剑指offer)
8.链表中倒数第k个结点(剑指offer)
9.数组中超过一半的数字(剑指offer)
10.左旋转字符串(剑指offer)
11.把二叉树打印成多行(剑指offer)
12.旋转数组查找(剑指offer)
13.链表归并排序
14.Trapping Rain Water https://leetcode.com/problems/trapping-rain-water/
15.Longest Palindromic Substring https://leetcode.com/problems/longest-palindromic-substring/
16.Gray Code https://leetcode.com/problems/gray-code/
17.Binary Tree Maximum Path Sum https://leetcode.com/problems/binary-tree-maximum-path-sum/
18.Search for a Range https://leetcode.com/problems/search-for-a-range/
19.算术表达式转逆波兰表达式(后缀表达)
20.k-means
21.字符串由大小写字母组成,要求去重,只允许使用几个int临时变量,要求时间复杂度尽可能少
22.青蛙每次跳台阶,每次一步或者二步,青蛙总共可以跳n次,台阶共m阶(n<=m),每个台阶有若干害虫,使得青蛙吃的害虫最多。
23.左右括号组成的字符串,去除最少使得剩余的字符串是合法的(符合左右括号规则)
24.实现5选3 组合
25.数组中后面的数减前面的数差的最大值,要求时间、空间复杂度尽可能低
26.多个有序数组的归并
27.多个有序数组求交集
28.二个有序数组求差集
29.字符串中最长不重复子串
30.小于10万的回文数的个数

给定两个正整数x,y,x有两中状态转移方式:一个是f(x) = 2*x + 1,另一个是g(x) = 3*x+1,问x最少能够几次转移到y,转移不到输出-1。

int func(int x, int y){
if(x < 0) return -1;
if(x > y) return -1;
if(x == y) return 0;
int l = func(2*x+1,y);
int r = func(3*x+1,y);
if(l == -1 && r == -1) return -1;
if(l == -1) return r + 1;
return l + 1;
}

你可能感兴趣的:(知识点)