【问题标题】:Removing numbers from a large range of numbers从大量数字中删除数字
【发布时间】: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


【解决方案1】:

是否有某种算法或技术可以更快更有效地处理此类问题?

答案很大程度上取决于典型的用例:

  • 数字集通常是稀疏的还是密集的?
  • 您多久进行一次插入、删除和查找?
  • 在哪些模式中插入或删除数字(随机、连续、从末尾或开头)?
  • 有什么内存限制?

以下是通用解决方案的一些想法:

  • 创建一个存储范围而不是数字的结构。
  • 从单个条目开始:0 - MAX_VAL。
  • 范围可以有子范围。生成的范围图形成一棵树。
  • 删除数字会将叶子范围分成两部分,从而创建两个新叶子。

当集合很密集时(因为范围很少),这个算法会表现得很好。当你保持树平衡时,当图形增长(O(log n) 用于查找)时,它仍然会执行得有点快。

【讨论】:

  • 一个好主意,但如何使用索引?每个子树中存储的元素数量是否足够? (因此您不必遍历树来“手动”计数。)
  • 这是一组从 0 到 MAX_VAL 的连续数字。它可以很容易地用一个范围来表示,因为它包括中间的每个数字。同样,范围是静态的,一旦代码被初始化就不会改变。插入/删除/查找的比例约为 30/30/40%。数字被随机删除和插入。没有内存限制。
  • @Jongware 对每个子树中的元素进行计数听起来是解决索引问题的好主意。计算一个数字的索引会比较快:O(log n)。
【解决方案2】:

现在,假设您“删除”了 1、4、5 和 7:

Values: 0, -100, 2, 3, -100, -100, 6, -100, 8, 9// use a unique value that doesn't used in array
Index:  0, 1, 2, 3, 4, 5, 6, 7, 8, 9

【讨论】:

  • 这些值是无符号整数,但即使它们是有符号的,仍然需要我遍历给定索引之前的所有值,以及给定索引之后的任何连续值(如果该索引指定删除的值。如果我试图检索接近范围末尾的值,这将非常昂贵。
猜你喜欢
  • 2015-08-09
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多