优先队列,其中值是两种货币的总和,popMin 采用汇率
Priority queue where values are a sum of two currencies and popMin takes an exchange rate
我想定义一个优先级队列,其中优先级具有两种不同货币的组件。例如,商品 A 的价格为 1 美元 + 20 日元。这个队列有两个方法,insert(priceInUsd, priceInYen)
和 popMin(exchangeRate)
,它以美元和日元的价格为准,并在给定汇率的情况下弹出美元和日元总成本最低的项目。我该如何实施?
到目前为止,这是我的想法:
- 使用k-d树。插入需要 log(n)。我认为您可以通过对普通的 k-d 树最近邻算法进行微小修改来实现 findMin,因此据称这应该花费 log(n) 时间。维基百科对 k-d 树最近邻是否真的是 log(n) 如果你有糟糕的数据最坏的情况持谨慎态度,所以我不确定这一点。此外,我从未见过一个看起来特别可靠的消息来源声称 kd-trees 允许 log(n) 插入。
- 维护点的凸包,想getMin的时候循环遍历其中的所有内容。最坏的情况 n,但如果你的凸包中只有正常
n**(1/3)
的东西,这平均是没问题的。
有一些你没有提到的现有技术,dynamic planar convex hull problem. Brodal and Jacob (FOCS '02) 给出了一个数据结构,可以让你插入一个点,删除一个点,并找到一个极值点direction in amortized logarithmic time,这足以实现你的数据结构(尽管实现看起来很复杂)。
这是一个简单的答案,它提供 O(√n) 次插入和 O(√n log n) 次弹出分钟数。
点被保存在 O(√n) 个 bin 之一中。每个 bin 都有一个为其计算的凸包,按 atan2(yen, usd)
的顺序存储(尽管您不需要 trig 来比较两个点)。插入的填充顺序是这样的:
Bin 0: 0 2 5 9 14
Bin 1: 1 4 8 13
Bin 2: 3 7 12
Bin 3: 6 11
Bin 4: 10
...
要插入一个点,请为其分配一个 bin 并重新计算该 bin 的凸包。这是 O(√n) 时间,如果您将点按角度排序排列在数组中并重新运行 Graham 扫描。
对于pop-min,我们找到要删除的点,将其删除,并用另一个bin中的点替换它,以保持正确的bin大小集(插入后,这是那个bin刚刚插入)。这个操作的有趣部分是发现。要在凸包上找到给定汇率的最小总值,请使用二分搜索根据角度顺序在凸包上找到前驱和后继,然后 return 这两者的最小值。
我想定义一个优先级队列,其中优先级具有两种不同货币的组件。例如,商品 A 的价格为 1 美元 + 20 日元。这个队列有两个方法,insert(priceInUsd, priceInYen)
和 popMin(exchangeRate)
,它以美元和日元的价格为准,并在给定汇率的情况下弹出美元和日元总成本最低的项目。我该如何实施?
到目前为止,这是我的想法:
- 使用k-d树。插入需要 log(n)。我认为您可以通过对普通的 k-d 树最近邻算法进行微小修改来实现 findMin,因此据称这应该花费 log(n) 时间。维基百科对 k-d 树最近邻是否真的是 log(n) 如果你有糟糕的数据最坏的情况持谨慎态度,所以我不确定这一点。此外,我从未见过一个看起来特别可靠的消息来源声称 kd-trees 允许 log(n) 插入。
- 维护点的凸包,想getMin的时候循环遍历其中的所有内容。最坏的情况 n,但如果你的凸包中只有正常
n**(1/3)
的东西,这平均是没问题的。
有一些你没有提到的现有技术,dynamic planar convex hull problem. Brodal and Jacob (FOCS '02) 给出了一个数据结构,可以让你插入一个点,删除一个点,并找到一个极值点direction in amortized logarithmic time,这足以实现你的数据结构(尽管实现看起来很复杂)。
这是一个简单的答案,它提供 O(√n) 次插入和 O(√n log n) 次弹出分钟数。
点被保存在 O(√n) 个 bin 之一中。每个 bin 都有一个为其计算的凸包,按 atan2(yen, usd)
的顺序存储(尽管您不需要 trig 来比较两个点)。插入的填充顺序是这样的:
Bin 0: 0 2 5 9 14
Bin 1: 1 4 8 13
Bin 2: 3 7 12
Bin 3: 6 11
Bin 4: 10
...
要插入一个点,请为其分配一个 bin 并重新计算该 bin 的凸包。这是 O(√n) 时间,如果您将点按角度排序排列在数组中并重新运行 Graham 扫描。
对于pop-min,我们找到要删除的点,将其删除,并用另一个bin中的点替换它,以保持正确的bin大小集(插入后,这是那个bin刚刚插入)。这个操作的有趣部分是发现。要在凸包上找到给定汇率的最小总值,请使用二分搜索根据角度顺序在凸包上找到前驱和后继,然后 return 这两者的最小值。