【问题标题】:Integer assignment in range范围内的整数赋值
【发布时间】:2014-07-24 10:29:53
【问题描述】:

我正在寻找一种从某个区间 [a,b] 分配和释放整数的算法。

每次我们请求赋值时,算法都会在 [a,b] 范围内生成一个之前没有赋值过的整数。 我们可以通过要求算法释放之前分配的整数来释放它们。这样做会使它们再次可用于分配。

总结一下:

  • 整数赋值后,直到释放后才能再次赋值
  • 如果没有分配一个或多个整数,算法必须分配其中一个
  • 当且仅当分配范围内的所有整数时,算法才分配无

希望算法的时间和空间复杂度都是次线性的(对于 n = b - a)。

作为额外要求,假设 [a,b] 中的某些特定整数需要初始分配。

【问题讨论】:

  • 我可能错了,但我觉得我们可以使用与the pigeonhole principle 类似的逻辑来证明使用小于线性空间是不可能的。
  • 听起来像一个稀疏集。见stackoverflow.com/questions/361040/…
  • @user2007447:(1) 散列使用的远不止线性空间,(2) 线性搜索只是愚蠢的 (3) 我看不出对“随机”的要求或建议。
  • 如果 O(n) 空间是可以接受的,你可以用一个简单的队列来做到这一点。这将为您提供 O(1) 分配和 O(1) 释放。
  • 在最坏的情况下绝对不能使用次线性空间,因为可用数字有 2^n 种可能的不同模式,并且每个模式都需要用不同的位模式表示。这意味着我们至少需要 lg(2^n) = n 位。

标签: algorithm data-structures language-agnostic computer-science


【解决方案1】:

首先想到的是从一个“可用”范围开始。当用户分配一个整数时,只需将其从范围中删除即可:

        [a,b]
a <---  [a+1,b]

这在所有情况下都是 O(1) 操作。由于返回步骤的工作方式,这意味着只有在没有其他数字可用时才分配最大数字,并且尽可能频繁地重用低数字。

当用户返回一个整数时,进行二分搜索以确定它在哪个范围之前,或者合并到哪个范围:

[28][30-50]     <---- user is going to release 29
[28-50]
-or-
[26][30-50]     <----- user is going to release 28
[26][28][30-50]

这是一个 O(log m) 运算,其中 m 是 范围 的数量,通常非常小。它从 1 开始,但最多可以是 n/2,具体取决于用户释放的数字。

如果您想变得非常棘手,您可以在范围上添加第二个排序,将较小的范围移近“前”,将较大的范围移近“末端”,并且当用户输入数字时“可用”,您给它们“最小”范围内的第一个值,这会启发式地导致“消耗”较小的集合,从而减少总集合,从而平均节省空间。然而,这增加了很多复杂性,以及少量的空间和时间,所以最坏的情况会变得更糟。在尝试之前先测量。

值得一提的是,这个确实使用线性空间,虽然我很确定常数是

一些动态内存调度的工作原理与此类似,通常将“未使用”部分存储为链表未使用内存中。这样,就不需要额外的开销空间。由于您处理的是整数范围而不是堆内存,因此这种优化可能对您没有帮助。

【讨论】:

  • 不过,这确实有 O(n) 的空间复杂度,
  • @Thanix:确实如此,虽然常数是
猜你喜欢
  • 1970-01-01
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多