两道O(n)面试题

两道O(n)面试题

 

1.       给你一个长度为N的链表。N很大,但你不知道N有多大。你的任务是从这N个元素中随机取出k个元素。你只能遍历这个链表一次。你的算法必须保证取出的元素恰好有 k个,且它们是完全随机的(出现概率均等)。 

 

保存前k个元素于集S. 从第k+i(i>0)个开始, r1=rand(1,k+i), 如果r1>k, 则保持现有的选择集合S不变 . 如果r1<=k, r2=rand(1,k),并让第k+i元素(即当前元素)替换集合S里第r2个元素 .

Reservoir Sampling (蓄水池抽样)

                       Init : a reservoir with the size k

 

                       for   i= k+1 to N

                              M=random(1, i);

                              if( M < k)

                                      SWAP the Mth value and ith value

                        end for

 

每个元素被选择的都是等概率k/n.

 

证明 :

 

P1=P2=…=Pk=∏i=1n-k [ i/(k+i)+(k/(k+i))*((k-1)/k) ] =(k/k+1) * (k+1)/(k+2) *...*(n-1)/n =k/n

 

设1<=i<=n-k

Pk+i= k/(k+i) *∏ j=1n-k[(i+j)/(k+i+j)+k/(k+i+j)*(k-1)/k)]

       = k/(k+i) *[(k+i)/(k+i+1) * (k+i+1)/(k+i+2) *...*(n-1)/n]

       = k/(k+i) * (k+i)/n

       = k/n

 

 

2.       给你一个数组A[1..n],请你在O(n)的时间里构造一个新的数组B[1..n],使得B[i]=A[1]*A[2]*…*A[n]/A[i]。你不能使用 除法运算。

 

可拆分为B[i]=A[1]*A[2]*…*A[i-1] +A[i+1]*A[i+2]*…*A[n],遍历2次即可求得.

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值