常见--一些算法的总结

1.动态规划问题--最大连续子数组和

  • 统计日志里面某个函数出现的次数(海量数据处理)
  • 很多台服务器产生的日志,需要找出距离当前时间最近的1000条日志

2.数组

  • 给一个数组,判定其中是否有重复元素
  • 一个有序数组,判断其中是否有重复元素,如果有返回其起始和结束的位置,如果没有则返回-1
  • 给定一个数组a[]和一个数字b,在数组里找两个数,和为b,返回两个数的下标?
  • 随机生成[0.m]间n个正整数,不重复。时间复杂度是多少?
  • 输入数组和整数m,将数组左移m位,时间复杂度要求O(n)
  • 旋转数组里找某一个数是不是存在
  • 输入数组,判断数组中第一个满足其左侧的数字均小于该数,右侧均大于该数的下标。
  • 时间复杂度是多少?如何优化?
  • 给定两个字符串数组s1和s2,(无重复元素)求s2是由s1删除了哪些元素得到?(例如s1={"a","b","c","d","e"}, s2={"a","e","c"}, 结果应该为{"b","d"})

3.排序问题,算法复杂度

  • 手写快排,冒泡
  • 合并两个有序链表

4.链表问题

  • 找链表的中点,环

5.树的问题

  • 多叉树的所有节点的深度和
  • 寻找二叉树上两个节点的最近父节点
  • 使用两个vector实现一个栈,用两个栈实现一个队列

6.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次即可。

7.海量数据的top k 问题:

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

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

8.选取频率最高问题

海量数据的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求频率,最后归并

9.智力题

  • 假如有五个犯人12345,需要杀的顺序为1354,只有2存活;假如6个犯人,13526,4存活;现在问你假如有n个人最后谁存活(用链表处理简单,面试官告诉我还有更好的,我用的是最简单方法)
  • 称苹果,9堆每个40g,1堆每个50个,找出50g的那堆?

一堆拿1个,然后一堆拿2个...最后一堆拿10个,一共55个,合起来若是54*40+50,那就是在拿1个的那堆,以此类推。

  • 手中一幅扑克牌,假设顺序为ABCDEF,把第一张放到桌面上,第二张挪到最后,第三张放到桌面,第四张挪到最后,一直到所有牌都在桌面

BCDEF   A
CDEFB
DEFB   AC
EFBD
...

把最后在桌面上的这副牌给你,求出原始牌的顺序

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

10.别人的一些算法的总结

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;
}


猜你喜欢

转载自blog.csdn.net/sinat_21026543/article/details/79825623