【发布时间】:2015-08-20 07:43:40
【问题描述】:
我遇到了以下问题,正在尝试寻找更优化的解决方案。
假设您有一个介于 0 和 9 之间的数字范围:
Values: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
现在,假设您“删除”了 1、4、5 和 7:
Values: 0, -, 2, 3, -, -, 6, -, 8, 9
Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
在没有值的地方,所有后续的值都向左移动:
Values: 0, 2, 3, 6, 8, 9
Index: 0, 1, 2, 3, 4, 5
索引 1 处的值现在变为 2(原为 1),索引 2 处的值现在为 3(原为 2),索引 3 处的值现在为 6(原为 3),等等。
这就是问题所在。我需要在更大的范围内管理这个,多达数万个值。这些值的随机数量将从原始连续范围中删除,并可能在之后添加回来(但与删除顺序不同)。起始状态将始终是 0 到 MAX_VAL 之间的完整数字序列。
我尝试过的事情:
1) 维护一个值数组,从该数组中删除值,并将所有内容移一位。这失败了,因为您正在迭代刚刚删除的值之后的所有值,结果太慢了。之后获取给定索引的值确实很快。
2) 维护一个值的链接列表,并通过将其拉出列表来删除该值。添加/删除值和获取给定索引处的值似乎都很慢,因为我需要先遍历列表。
3) 跟踪“删除”的值,而不是维护一个从 0 到 MAX_VAL 的巨大数组/列表/等值。如果删除的值存储在有序数组中,那么计算给定索引之前和之后删除了多少值就变得微不足道,而是只返回一个偏移索引。这有点工作,只是维护已删除值的有序数组并对其进行迭代很慢,尤其是在已删除值的数量接近 MAX_VAL 时。
是否有某种算法或技术可以更快更有效地处理此类问题?
【问题讨论】:
-
恕我直言,我认为第三个选项是最好的。您可以使用位图,而不是保留另一个数组。使用系统拥有的最大无符号数,并将这些位用作存在与否的标记。
-
你不能将这些值存储在一个字符串中,然后将每个数字都复制到另一个字符串中,除了你要删除的那个吗?
-
您可以立即move all of them,而不是手动将每个数字移到您在数组中删除的数字之上。至少它会比你一次做一个数字更有效率一点。
-
问题变成了“哪种数据结构提供最有效的遍历以及有效的插入和删除?”这不是一个简单的问题,因为它高度依赖数据。在您的情况下,红黑树可以快速访问任何要删除的元素,但插入和删除本身的成本很高。所以在优化中,你必须回答的问题是大多数操作发生在哪里?遍历?插入/移除?然后,您可以缩小数据结构的选择范围。 (对于简单的整数,很难在速度上击败数组)
-
大约是 30/30/40% 的拆分(添加、删除和获取索引值)。平均而言,我处理的值从 7.5K 到 80K 不等。
标签: c arrays linked-list range