如何在假硬币算法中称重
How to Weigh in Fake Coin Algorithm
我正在尝试为假币问题开发C++代码。我正在使用一个二进制数组 n 长,填充 1 和一个随机 0 来表示假币。当我将数组分成两半以比较权重时,如何确定每条边的权重?
我可以很容易地计算每个数组中的 1 的数量,但这将是一个线性运行时间。整体算法应该是亚线性的。
有没有办法确定每个数组在恒定时间内的权重?
披露:这是一项学校作业,所以希望你能在不给出完整答案的情况下给出提示。
作为一名学生,我会坚持这一点,因为您每半数1 的数量,并且您有效地使用了这种方法:
减少和征服
因此,您实际上是在称量 O(log2n) 次,这使得算法成为亚线性。
我的观点是,优化算法的是您正在执行的称重次数及其有效空间(一半与总数)。
在此 CS 会话中阅读更多内容,建议您在 3 时拆分,您可以做得更好并达到 O(log3n)。但是,如果您是新手,那么现在分成两半就可以了!=)
如果你想玩一些代码,你可以使用 std::bitset,它提供 count(),它返回位集中的 1 个数。
我可以很容易地计算每个数组中的 1 的数量,但这将是一个线性运行时间。整体算法应该是亚线性的。
我想你在这里弄错了。整个算法不可能是亚线性的,很容易理解为什么:要至少读取每个硬币,你需要线性时间,因为硬币数量显然是线性数量的硬币。很明显,如果不至少阅读一次每枚硬币,就无法找到假硬币。(更严格地说,您需要阅读所有硬币,但至少一次,但这仍然是线性的。
因此,其他答案和评论表明,您需要称硬币的次线性次数,我倾向于同意这一点。
如果您仍然想更快地进行比较(即范围内的总和),有一种称为 Fenwick 树的数据结构,它允许您以对数时间计算子范围总和,但仍需要线性时间来构建。但是请注意,我认为将其用于您的任务在复杂性(它可能比您当前的级别更高级)和性能奖励方面都是矫枉过正(仅当您要在阵列上运行许多range
查询并且您将要更改数组时才有意义)。
另请注意,维基文章的第二段提出了一个简单的算法,它只需要线性时间进行初始化,然后在恒定时间内计算前缀和(从而计算范围和):只需再创建一个带有硬币前缀和的数组(或者如果您不再需要它,甚至可以就地更新原始数组)。显然RangeSum(a,b) = PrefixSum(b) - PrefixSum(a-1)
(其中PrefixSum(-1)
为 0)。如果你想炫耀,实现这个可能是有意义的,但就 Big-O 而言,仍然没有性能奖励。
- 最小硬币更换问题(自上而下方法)
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 排序算法c++
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- 下面是排序算法O(n)吗
- KMP算法和LPS表构造的运行时间
- 为什么我的排序算法会更改数组值
- 求最大元素位置的分治算法
- 具有非整数边容量的最大流量的Dinic算法
- 到连接组件算法的问题(递归)
- 如何在假硬币算法中称重
- 硬币兑换的贪婪算法c++
- 算法将一个硬币矩阵转移到另一个硬币阵列
- 是硬币变化算法,输出仍可由DP解决的所有组合
- 确定硬币组合的算法