-
给出N个数,如何找出top k个值:随机快排、堆。
-
C++ 五大内存分区:堆、栈、全局/静态存储区、字符串常量区和代码区。
-
随机打乱N个数,使得每个数在每个位置的概率为 1 N \frac{1}{N} N1。 完美洗牌问题:
# 完美洗牌问题 # 令N个数存在一个列表/数组中 for i in 1~N: num = random(1, i) # 生成1~i的之间的随机数 swap(num, i) # 交换下标为i和小标为num的数的位置
证明:
利用数学归纳法:
-
当 N = 1 时,即当前仅有一个数,此数在每个位置的概率为1(此时仅有一个位置),满足概率 1 N \frac{1}{N} N1。
-
证明,若当 N = K 时,每个数在满足各个位置的概率为 1 N \frac{1}{N} N1,那么就有 N = K + 1 时,每个数在各个位置的概率为 1 K + 1 \frac{1}{K+1} K+11(= 1 N \frac{1}{N} N1)。
-
对于第 K + 1 个数,易知其在 1~K+1 中任意位置的概率为 1 K + 1 \frac{1}{K+1} K+11。
-
对于前 K 个数,已知有一数 a (1<=a<=K) 其在 1~K 中任意位置的概率为 1 K \frac{1}{K} K1 ,现在插入第 K + 1 个数,其不与 a 交换的概率为 1 − 1 K + 1 1 - \frac{1}{K+1} 1−K+11,所以插入新数字后有,数 a 出现在任意位置的概率为:
1 K ∗ ( 1 − 1 K + 1 ) = 1 K + 1 \frac{1}{K}*(1-\frac{1}{K+1}) = \frac{1}{K+1} K1∗(1−K+11)=K+11
-
-
-
给定1、2、5、10、20、50面额的纸币,给定一个数N,如何用最少面额纸币凑N。
错误解法:贪心
正确解法:动态规划
写代码。
# 凑多少元 N = 24 # 新增12元纸币,这也是为什么不能用贪心的原因 money = [1, 2, 5, 10, 12, 20, 50] big_int = 99999 # 自定义一个较大的数 t = [big_int] * (N + 1) def solve(): for i in range(1, N+1): if i in money: # 一张纸币能付清的情况 t[i] = 1 else: tmin = big_int for j in money: if j >= i: continue z = t[i - j] # 找最少的纸币数 if z < tmin: tmin = z t[i] = tmin + 1 solve() print t[N]
-
现有一日志,每个记录中有IP,统计该日志(大文件)中出现次数最多的top K个IP。
我的解法:时间复杂度O(nlogn)
-
需要统计 <IP – 个数>,这样的键值对,采用字典数据结构。
-
考虑到IP地址很多(ipv4),又是字符串,作为键将占用大量内存,需用hash方法将IP地址转为一个数。
-
考虑到文件很大,无法一次性存入全部IP(就算将其转为int32的一个数),于是需要将文件进行切分,具体方法为,对IP进行映射,例如取模N,然后将该数据写入对应文件。此做法保证相同IP映射到同一文件。
-
分别遍历各个文件,统计IP频度,取top K条记录,利用快排、堆等算法即可。
-
此时获取到NK个键值对,再利用快排、堆等算法取top K条记录即可。
-
将int32计算回ip地址。
-
百度策略岗(C++)面试复盘
最新推荐文章于 2022-08-15 17:30:25 发布