这是笔者学习 Stanford cs 168 课程的一些学习笔记
lecture 2, 主要讲一个基于 hash 和独立试验思想,设计的一种数据结构 count min sketch,想法非常类似于 bloom filter,都是以牺牲准确率换空间和时间。
heavy hitter problem
Find majority element
先来看一个简单的在面试中经常会遇到的问题,找主要元素
问题如下: 一组数据流: a 1 , … , a n a_1,\dots,a_n a1,…,an, 存在一个元素 a i a_i ai 保证出现次数大于
n / 2 n/2 n/2。 能否设计一个算法在 仅仅扫描一遍的情况下找到它。
这里有一个很 cute 的算法
current = -1
counter = 0
for e in stream:
if counter == 0:
current = e
counter += 1
elif e == current:
counter += 1
else counter -= 1
return current
可以证明这个算法一定是正确的。
证明
数学归纳法
- 当 len(stream) = 1 的时候,一定是正确的
- 假设当 len(stream)<=n 的时候是正确的
- 当 len(stream) = n+1 的时候
- 如果 a 1 a_1 a1 是ans,当 counter 第一次减少为0 的时候,流被分为两段,一段是走过的,另外一段是没有遍历过的,[s_1|counter=0|,s_2],设 l 1 , l 2 l_1,l_2 l1,l2 分别是两段的长度,显然,第一段中 c n t ( a 1 ) = s 1 / 2 cnt(a_1)=s_1 / 2 cnt(a1)=s1/2 , 由于 a 1 a_1 a1 是答案,它在整个序列中出现的次数大于 ( n + 1 ) / 2 (n+1)/2 (n+1)/2 因此在 s 2 s_2 s2 中,我们有 c n t ( a 1 ) > n + 1 2 − s 1 2 = s 2 2 cnt(a_1) > \frac{n+1}{2}-\frac{s_1}{2}=\frac{s_2}{2} cnt(a1)>2n+1−2s1=2s2 ,同时 l e n ( s 2 ) < = n len(s_2) <=n len(s2)<=n 因此,由数学归纳法,再第二段中能正确找到答案。
- 如果 a 2 a_2 a2 不是 ans,遍历第一段的时候, c n t ( a n s ) < s 1 2 cnt(ans) < \frac{s_1}{2} cnt(ans)<2