我们有一个排序数组,我们希望将一个索引的值仅增加 1 个单位 (array[i]++),这样生成的数组仍然是排序的。这在 O(1) 中可能吗?可以在 STL 和 C++ 中使用任何可能的数据结构。
在更具体的情况下,如果数组由所有 0 值初始化,并且始终仅通过将索引的值增加 1 来增量构造,是否存在 O(1) 解决方案?
原文由 Farshid 发布,翻译遵循 CC BY-SA 4.0 许可协议
在更具体的情况下,如果数组由所有 0 值初始化,并且始终仅通过将索引的值增加 1 来增量构造,是否存在 O(1) 解决方案?
不。给定一个全 0 的数组: [0, 0, 0, 0, 0]
。如果您增加第一个值,给出 [1, 0, 0, 0, 0]
,那么您必须进行 4 次交换以确保它保持排序。
给定一个没有重复的排序数组,那么答案是肯定的。但是在第一次操作之后(即第一次递增),您可能会有重复项。您执行的增量越多,重复的可能性就越高,并且越有可能花费 O(n) 来保持该数组的排序。
如果您只有数组,则不可能保证每次增量少于 O(n) 时间。如果您正在寻找的是支持排序顺序和按索引查找的数据结构,那么您可能需要一个 顺序静态树。
原文由 Jim Mischel 发布,翻译遵循 CC BY-SA 3.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.4k 阅读
1 回答1.6k 阅读✓ 已解决
我还没有完全解决这个问题,但我认为总体思路可能至少对整数有所帮助。以更多内存为代价,您可以维护一个单独的数据结构,该结构维护一系列重复值的结束索引(因为您希望将增量值与重复值的结束索引交换)。这是因为重复值会遇到最坏的情况
O(n)
运行时:假设您有[0, 0, 0, 0]
并且您在位置0
处增加值。然后是O(n)
找出最后一个位置(3
)。但是假设您维护我提到的数据结构(地图可以工作,因为它具有
O(1)
查找)。在这种情况下,你会有这样的事情:因此,您有一系列
0
值在3
位置结束。当您增加一个值时,假设在位置i
,您检查新值是否大于i + 1
的值。如果不是,那你很好。但如果是,则查看辅助数据结构中是否有此值的条目。如果没有,您可以简单地交换。如果 有 条目,则查找结束索引,然后与该位置的值交换。然后,您需要对辅助数据结构进行任何更改以反映数组的新状态。一个更彻底的例子:
二级数据结构是:
假设您增加位置
2
的值。因此,您已将3
增加到4
。数组现在看起来像这样:您查看下一个元素,即
3
。然后,您在辅助数据结构中查找该元素的条目。条目是4
,这意味着有一个 --- 的运行以3
4
。这意味着您可以将当前位置的值与索引4
处的值交换:现在您还需要更新辅助数据结构。具体来说,
3
的运行提前结束了一个索引,因此您需要减少该值:您需要做的另一项检查是查看该值是否已重复。您可以通过查看
i - 1
th 和i + 1
th 位置来检查它们是否与所讨论的值相同。如果两者都不相等,那么您可以从映射中删除该值的条目。同样,这只是一个一般性的想法。我将不得不对其进行编码,以查看它是否按我的想法工作。
请随意戳洞。
更新
我 在这里 用 JavaScript 实现了这个算法。我使用 JavaScript 只是为了快速完成。另外,因为我很快就编写好了它,所以它可能会被清理掉。不过我确实有意见。我也没有做任何深奥的事情,所以这应该很容易移植到 C++。
该算法基本上有两个部分:递增和交换(如果需要),以及在地图上完成的簿记,以跟踪我们的结束索引以查找重复值的运行。
该代码包含一个测试工具,该工具以零数组开头并增加随机位置。在每次迭代结束时,都会进行测试以确保数组已排序。