loops - 将循环的线性时间转换为 log(n) 时间函数?
问题描述
在一次采访中,我被要求描述一个函数,它可以返回一个给定对象的随机数{names:weights}
作为输入。我将被允许使用库来生成介于两者之间的数字,[0,1]
但仅此而已。我回答说任务需要分解为:
确保权重是累积的
[0.25, 0.5, 0.25]
->[0.25, 0.75, 1]
,保存为c_arr
[0,1]
在另存为 a之间产生一个随机数,然后通过for 循环val
遍历我的。c_arr
如果val
是 > 中的ith
元素c_arr
,则继续,否则返回与该ith
元素关联的名称。
我的面试官注意到这是可以接受的,但是,问我是否可以使用大 O 表示法来表达它的性能。我在这里不是很了解,但回答应该是线性时间。他回答说这是真的;但是,伪函数可以随着log(n)
时间改进。
据我所知,log(n)
时间意味着不遍历范围内的每个整数,[0,1,2,3,4,5,6,7,8...x]
而是像[1,2,4,8,...X]
. 我不确定这是否得到验证。但即使是这样,我也不确定如何改进伪代码函数,使其不需要以c_arr
线性方式遍历每个元素。
有人可以解释一下吗?
解决方案
https://softwareengineering.stackexchange.com/questions/150616/get-weighted-random-item/288599
从 Orionii 皇帝那里窃取答案 [我不相信]:
现在到有趣的部分。这种方法的效率如何?最有效的解决方案是什么?我的一段代码需要 O(n) 内存并在 O(n) 时间内运行。我不认为它可以用少于 O(n) 的空间来完成,但时间复杂度可以低得多,实际上是 O(log n)。诀窍是使用二进制搜索而不是常规的 for 循环。
double r = Random.Next() * totalSum;
int lowGuess = 0;
int highGuess = fruit.Count - 1;
while (highGuess >= lowGuess)
{
int guess = (lowGuess + highGuess) / 2;
if ( csum[guess] < r)
lowGuess = guess + 1;
else if ( csum[guess] - weight[guess] > r)
highGuess = guess - 1;
else
return fruit[guess];
}
还有一个关于更新权重的故事。在最坏的情况下,更新一个元素的权重会导致更新所有元素的累积和,从而将更新复杂度增加到 O(n)。这也可以使用二叉索引树减少到 O(log n)。
推荐阅读
- reactjs - 为什么类型在枚举中没有重叠?
- java - 使用 java 在 rhino 中调用 chartjs
- django - Creating functional classes in Django that provide deployment pipeline functionality
- rest - Can I invent my own HTTP Status Code for when an entity is updated and the server returns a representation of the updated entity?
- c# - 匹配数组
SqlParser.Parser 的输出? - .net - 如何批量插入SQL Server数据库?
- javascript - 按类名的按钮选择的单选按钮组
- python-3.x - 如何在 SQLAlchemy 中获取 SQL Server 函数调用的结果
- mysql - 在 MySQL 表中删除外键时如何修复错误?
- django - 如何使具有多个后备的 try_files 在 nginx 中工作?