二进制搜索 - 有人可以清除这种访谈算法吗?

时间:2015-08-23 18:06:02

标签: arrays algorithm binary-search

我最近接受采访时面试官给了我以下情景,并问我用什么数据结构来实现它:

你有100个大理石,每个大理石是红色,蓝色或绿色。大理石被扔进一个袋子,你需要有一些机制来取回随机颜色的大理石(有替换)。

好的,很简单。在询问了有关约束的一些问题之后,我告诉他我会使用一个简单的数组,其中每个桶代表一个大理石。随机数函数可用于索引数组,从而产生随机彩色大理石。

那个解决方案很好,但后来他问“如果你有很多不同的颜色,每个都有< = 1,000,000,000大理石?”最初我建议使用哈希表,其中每个键代表一种颜色,每个值代表该颜色的弹珠数。采访者告诉我,这是对空间约束的一个很好的解决方案,但现在产生n种颜色之一的概率是1 / n,而不是大理石总数给出的实际概率。我需要一些方法来保持概率相同而不将它们全部存储在内存中。我最终没有想到任何事情,他给我的解决方案是:

找到每种颜色的总和(这将是O(n),这对于设置来说很好)并设置一个数组,其中每个桶代表每种颜色的累积总和。例如,如果你的大理石总数是R:3,B:5,G:1,000,000,000,那么数组看起来像[3] [8] [1,000,000,008]。然后他说你现在可以使用随机索引的二元搜索来获得随机颜色的大理石,同时仍保持正确的概率。任何人都可以向我解释为什么会这样吗?这只是一个修改后的二进制搜索,它返回的第一个值高于你的随机索引吗?

2 个答案:

答案 0 :(得分:1)

诀窍在于您查看二进制搜索结束的索引而不是该位置的值。我还不知道这个算法。谢谢你的描述。我在python中为你实现了它:)

import random
import bisect

# 10 red, 20 blue, 70 green
counts = [10, 20, 70]
sums   = [10, 30, 100]

# count how often some color occurs to verify later that the algorithm works correctly
bins = [0, 0, 0]
# randomly select 10000 colors
for _ in range(100000):
    random_index = random.randint(0, sums[-1]) # sums[-1] is the last value in array (100)
    # do binary search in sums array
    result = bisect.bisect_left(sums, random_index)
    bins[result] += 1

print(bins) # example output: [10875, 19732, 69393]

答案 1 :(得分:0)

如果在选择大理石颜色时有1到N之间的随机索引,则获得特定颜色的概率为k / N,其中k是分配给该颜色的数字的数量。您的采访者只是按顺序放置颜色,以便每种颜色都有正确的数字k指定的索引(其中k是该颜色的原始大理石的数量),然后注意到给定1和N之间的随机索引,可以二进制搜索以找出随机索引所在的颜色范围。假设1和N之间的随机索引是均匀随机的,这将为您提供当有k个大理石时获得颜色的正确概率k / N.那种颜色。