1,求第K大数 (http://www.cnblogs.com/zhjp11/archive/2010/02/26/1674227.html)
解法1: 我们可以对这个乱序数组按照从大到小先行排序,然后取出前k大,总的时间复杂度为O(n*logn + k)。
解法2: 利用选择排序或交互排序,K次选择后即可得到第k大的数。总的时间复杂度为O(n*k)
解法3: 利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。
时间复杂度近似为O(n)
解法4: 二分[Smin,Smax]查找结果X,统计X在数组中出现,且整个数组中比X大的数目为k-1的数即为第k大数。时间复杂度平均情况为O(n*logn)
解法5:用O(4*n)的方法对原数组建最大堆,然后pop出k次即可。时间复杂度为O(4*n + k*logn)
解法6:维护一个k大小的最小堆,对于数组中的每一个元素判断与堆顶的大小,若堆顶较大,则不管,否则,弹出堆顶,将当前值插入到堆中。时间复杂度O(n * logk)
解法7:利用hash保存数组中元素Si出现的次数,利用计数排序的思想,线性从大到小扫描过程中,前面有k-1个数则为第k大数,平均情况下时间复杂度O(n)
2,统计搜索最多的10个关键字
搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。
假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。
解法:
维护一个Key为Query字串,Value为该Query出现次数的HashTable,每次读取一个Query,如果该字串不在Table中,那么加入该字串,并且将Value值设为1;如果该字串在Table中,那么将该字串的计数加一即可。最终我们在O(N)的时间复杂度内完成了对该海量数据的处理。
利用求第K大数的方法求的top 10
3,求访问次数最多的IP
海量日志数据,提取出某日访问百度次数最多的那个IP。
解法:IP的数目还是有限的,最多2^32个,所以可以考虑使用hash将ip直接存入内存,然后进行统计。
4,hash表解决冲突
方法:不存储字符串而是存储另外两个hash值,这样当发生冲突时不需要比较字符串,只需要比较hash值。此方法不会保证完全正确,但是出错的概率特别小(1:18889465931478580854784)可以忽略
5,求矩阵最佳相乘顺序
问题:给定一个连乘的矩阵序列,选择一个适当的运算序列,使总的开销最小。
例如:v1 = ( [2,6] * [6, 8] ) * [8, 7] = 2*6*8 + 2*8*7 = 208
v2 = [2,6] * ( [6, 8] * [8, 7] ) = 6*8*7 + 2*6*7 = 420
解法:利用DP,
状态方程为 m[i,j] = min(m[i,k] + m[k+1,j] + a[i].x * a[k+1].x * a[j].y), i <= k <= j.
初始值为 m[i,i] = 0, 0<=i<=n
m[i,j]表示由矩阵i到矩阵j的矩阵串的最小乘积代价
m[0,n]为问题解
6,唱片排版(http://blog.youkuaiyun.com/fanshengchong/article/details/8588332)
问题:现有n首歌曲,从中选择一些来发行m张唱片,每张唱片至多包含t分钟的音乐,唱片中的歌曲不能重叠。按下面的标准进行选择:
(1) 这组唱片中的歌曲必须按照它们创作的顺序排序;
(2) 包含歌曲的总数尽可能多。
输入n,m,t,和n首歌曲的长度,它们按照创作顺序排序,没有一首歌超出一张唱片的长度,而且不可能将所有歌曲的放在唱片中。输出所能包含的最多的歌曲数目。
解法1:DP
m[i, j, k]=mim { m[ i-1 , j , k ], m[ i-1 , j , k - t[i] ] +1] }, 当k>=t[i]
m[i, j, k]=min { m[ i-1 , j , k ], m[ i-1 , j-1 , t - t[i] ] + m[ i-1 , 0 , k ] + 1 }, 当k<t[i]
其中m[i, j, k]表示用前i首歌,编辑j张盘加上k分钟能填入的最多歌曲数。
解法2:DP
g[i,j]=(a, b),0≤i≤n,0≤j≤i,0≤a≤m,0≤b≤t,表示在前i首歌曲中选取j首录制所需的最少唱片为:a张唱片另加b分钟。由于第i首歌分为发行和不发行两种情况,这样我们可以得到如下的状态转移方程和边界条件:
g[i,j]=min{g[i-1,j],g[i-1,j-1]+t[i]}
其中(a, b)+t[i]=(a’, b’)的计算方法为:
当long[i]≤t-b时: a’=a; b’=b+t[i];
当long[i]>t-b时: a’=a+1; b’=t[i];
规划的边界条件:
g[i,0]=(0,0) 0≤i≤n
这样题目所求的最大值是:ans=max{k| g[n, k]≤(m-1,t)}
7,平分大理石(http://blog.youkuaiyun.com/fanshengchong/article/details/8588332)
问题:有价值分别为1..6的大理石各a[1..6]块,现要将它们分成两部分,使得两部分价值和相等,问是否可以实现。
解法:设S为所有石头的重量和,则问题转化为取n块石头的和为s/2
8,石头游戏(http://blog.youkuaiyun.com/fanshengchong/article/details/8588332)
问题: 在一个操场上摆放着一排n(n≤20)堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试编程求出将n堆石子合并成一堆的最小得分和最大得分以及相应的合并方案。
解法1:DP
m[i,j] = min{ m[i, k] + m[k,j] | i<=k<=j} + sum(h[i..j])
其中m[i, j]表示将i到j堆石子合并的最小得分,h[i]表示第i堆石头的重量
解法2:利用四边形优化简化解法1
解法3:优化解法一,简化状态方程为
m[i,j] = min{ h[i]+m[i+1,j], m[i, j-1] + h[j]} + sum(h[i..j])
9,邮局问题(http://blog.youkuaiyun.com/fanshengchong/article/details/8588332)
问题:按照递增顺序给出一条直线上坐标互不相同的n个村庄,要求从中选择p个村庄建立邮局,每个村庄使用离它最近的那个邮局,使得所有村庄到各自所使用的邮局的距离总和最小。
解法:DP
m[i,j] 表示在前j个村庄简历i个邮局的最小距离和
其中w[i,j]表示在d[i..j]之间建立一个邮局的最小距离和
10,新石头游戏
问题:给定n堆石头,2个玩家。每个玩家可以的动作是选择一堆石头,从中扔掉至少一块石头,同时,他可以将该堆的石头拿走任意块并分发到其他任意多堆上。两个玩家轮流操作。最后没法操作的人输。求谁会赢。
答案:先操作的人获胜。
解法:
平衡状态:有n堆石头,每两堆一组,一组内的两堆的石头数相等。平衡状态是一个先手必败状态,原因是先操作的人的任何操作后操作的人都可以模拟。知道最后先手无法操作。
先操作的人可以通过一步如下操作到达平衡状态:
首先按照石头数排序。
如果初始有奇数堆石头-->拆掉最多的一堆石头,把余下各个堆填平成两两相等的数量。多余的石头扔掉。如下左图
如果初始有偶数堆石头-->拆掉最多的一堆石头,把余下各个堆填平成两两相等的数量,直到最后剩余一堆。将最多的一堆保留最小堆数目的石头,其余扔掉。如下右图
11,有序数组和小于k
问题:一个有序数组a,求满足a[i] + a[j] < k 的(i,j)数目
解法:
int count(int * s, int * e, int k)
{
int ret = 0;
while (s < e)
{
if (*s + *e < k)
{
ret += e - s;
s++;
}
else
{
e--;
}
}
return ret;
}
12,树的节点距离
问题:求n个节点的树满足节点距离小于k的节点对的数目。
解法:利用分治思想,先求出两节点距离的路径经过根节点的数目,再递归求解左,右子树的数目。
先将左子树的所有节点到root的距离排序为S1列表,再将右子树所有节点到root的距离排序为S2,合并S1,S2求出满足S1[i]+2[j]<k的数目 (O(n))。
int count(int* s1, int* s2, int n1, int n2)
{
int* i = s1+n1;
int* j = s2;
int ret = 0;
while (i != s1 && j != s2+n2)
{
if (*i + *j <= k)
{
ret += i - s1;
j++;
}
else
{
i--;
}
}
}
每次排序复杂度为O(n*lgn + n),递归深度为O(lgn),故总的时间复杂度为O(n*lgn*lgn)
13,硬币问题:
问题:有面值为Ai的硬币Ci个,有n种硬币.问价值在1到m的整数范围内, 有多少个价值能通过现有硬币的组合达到.
解法:多重背包问题,详见 背包九讲