- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
寻找逻辑上表示由唯一 id 键控的元素序列的数据结构(为了简单起见,我们将它们视为字符串,或者至少是可散列的对象)。每个元素只能出现一次,没有间隙,第一个位置为0。
应支持以下操作(用单字母字符串演示):
insert(id, position)
- 添加由 id
键控的元素进入偏移量 position
处的序列.自然地,序列中后面每个元素的位置现在增加一。示例:[S E L F].insert(H, 1) -> [S H E L F]
remove(position)
- 移除偏移量 position
处的元素.将序列中后面每个元素的位置减一。示例:[S H E L F].remove(2) -> [S H L F]
lookup(id)
- 找到由 id
键控的元素的位置. [S H L F].lookup(H) -> 1
lookup
,
remove
, 和
insert
.
lookup
可能用得最多,用
insert
和
remove
发生的频率足够高,最好不要是线性的(hashmap + array/list 的简单组合会得到你)。
lookup
, O(log n)
insert
/
remove
,但我实际上怀疑从纯粹的信息论角度来看这行不通(虽然我还没有尝试过),所以 O(log n)
lookup
还是不错的。
最佳答案
trie 和哈希映射的组合允许 O(log n) 查找/插入/删除。
trie 的每个节点都包含 id 以及有效元素的计数器,以该节点为根和最多两个子指针。一个位串,由左 (0) 或右 (1) 转决定,同时从根遍历特里树到给定节点,是值的一部分,存储在对应 id 的哈希映射中。
删除操作将树节点标记为无效并更新从删除节点到根的路径上所有有效元素的计数器。它还删除相应的哈希映射条目。
插入操作应该使用每个 trie 节点中有效元素的位置参数和计数器来搜索新节点的前驱和后继节点。如果从前驱到后继的有序遍历包含任何已删除的节点,则选择排名最低的一个并重用它。否则选择前任或后继,并为其添加一个新的子节点(前任的右 child 或后继的左 child )。然后更新从该节点到根的路径上所有有效元素的计数器,并添加相应的哈希映射条目。
查找操作从哈希映射中获取一个位串,并使用它从特里根到相应的节点,同时对这条路径左边的所有有效元素的计数器求和。
如果插入/删除的序列足够随机,则所有这些都允许每个操作的预期时间为 O(log n)。如果不是,则每个操作的最坏情况复杂度为 O(n)。为了让它回到 O(log n) 摊销复杂度,注意树的稀疏和平衡因素,如果删除的节点太多,重新创建一个新的完美平衡和密集的树;如果树太不平衡,则重建最不平衡的子树。
可以使用一些二叉搜索树或任何字典数据结构来代替哈希映射。代替位串,用于标识树中的路径,哈希映射可以存储指向树中相应节点的指针。
在此数据结构中使用 trie 的其他替代方法是 Indexable skiplist .
每个操作的 O(log N) 时间是可以接受的,但并不完美。正如 Kevin 所解释的那样,可以使用具有 O(1) 查找复杂度的算法来换取其他操作的更大复杂度:O(sqrt(N))。但这可以改进。
如果您为每个查找操作选择一定数量的内存访问 (M),则其他操作可能会在 O(M*N1/M) 时间内完成。这种算法的思想在 this answer to related question 中提出。 .那里描述的 Trie 结构允许轻松地将位置转换为数组索引并返回。该数组的每个非空元素都包含 id,哈希映射的每个元素都将此 id 映射回数组索引。
为了能够将元素插入到这个数据结构中,每个连续数组元素块都应该与一些空白空间交错。当其中一个块耗尽所有可用的空闲空间时,我们应该重建最小的一组块,与树中的某个元素相关,具有超过 50% 的空闲空间。当空闲空间总数小于50%或大于75%时,我们应该重建整个结构。
这种重新平衡方案仅针对随机和均匀分布的插入/删除提供 O(MN1/M) 摊销复杂度。对于 M > 2,最坏情况的复杂度(例如,如果我们总是在最左边的位置插入)要大得多。为了保证 O(MN1/M) 最坏情况,我们需要保留更多内存并更改重新平衡方案,以便它保持不变这:为整个结构保留至少 50% 的空白空间,为与顶级 trie 节点相关的所有数据保留至少 75% 的空白空间,为下一级 trie 节点保留 - 87.5% 等。
当 M=2 时,我们有 O(1) 的查找时间和 O(sqrt(N)) 的其他操作时间。
当 M=log(N) 时,我们对每个操作都有 O(log(N)) 时间。
但在实践中,较小的 M 值(如 2 .. 5)更可取。这可以被视为 O(1) 查找时间,并允许此结构(在执行典型的插入/删除操作时)以缓存友好的方式处理最多 5 个相对较小的连续内存块,并具有良好的矢量化可能性。如果我们需要良好的最坏情况复杂度,这也会限制内存需求。
关于data-structures - 用于快速位置查找的数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12017973/
初学者 android 问题。好的,我已经成功写入文件。例如。 //获取文件名 String filename = getResources().getString(R.string.filename
我已经将相同的图像保存到/data/data/mypackage/img/中,现在我想显示这个全屏,我曾尝试使用 ACTION_VIEW 来显示 android 标准程序,但它不是从/data/dat
我正在使用Xcode 9,Swift 4。 我正在尝试使用以下代码从URL在ImageView中显示图像: func getImageFromUrl(sourceUrl: String) -> UII
我的 Ubuntu 安装 genymotion 有问题。主要是我无法调试我的数据库,因为通过 eclipse 中的 DBMS 和 shell 中的 adb 我无法查看/data/文件夹的内容。没有显示
我正在尝试用 PHP 发布一些 JSON 数据。但是出了点问题。 这是我的 html -- {% for x in sets %}
我观察到两种方法的结果不同。为什么是这样?我知道 lm 上发生了什么,但无法弄清楚 tslm 上发生了什么。 > library(forecast) > set.seed(2) > tts lm(t
我不确定为什么会这样!我有一个由 spring data elasticsearch 和 spring data jpa 使用的类,但是当我尝试运行我的应用程序时出现错误。 Error creatin
在 this vega 图表,如果我下载并转换 flare-dependencies.json使用以下 jq 到 csv命令, jq -r '(map(keys) | add | unique) as
我正在提交一个项目,我必须在其中创建一个带有表的 mysql 数据库。一切都在我这边进行,所以我只想检查如何将我所有的压缩文件发送给使用不同计算机的人。基本上,我如何为另一台计算机创建我的数据库文件,
我有一个应用程序可以将文本文件写入内部存储。我想仔细看看我的电脑。 我运行了 Toast.makeText 来显示路径,它说:/数据/数据/我的包 但是当我转到 Android Studio 的 An
我喜欢使用 Genymotion 模拟器以如此出色的速度加载 Android。它有非常好的速度,但仍然有一些不稳定的性能。 如何从 Eclipse 中的文件资源管理器访问 Genymotion 模拟器
我需要更改 Silverlight 中文本框的格式。数据通过 MVVM 绑定(bind)。 例如,有一个 int 属性,我将 1 添加到 setter 中的值并调用 OnPropertyChanged
我想向 Youtube Data API 提出请求,但我不需要访问任何用户信息。我只想浏览公共(public)视频并根据搜索词显示视频。 我可以在未经授权的情况下这样做吗? 最佳答案 YouTube
我已经设置了一个 Twilio 应用程序,我想向人们发送更新,但我不想回复单个文本。我只是想让他们在有问题时打电话。我一切正常,但我想在发送文本时显示传入文本,以确保我不会错过任何问题。我正在使用 p
我有一个带有表单的网站(目前它是纯 HTML,但我们正在切换到 JQuery)。流程是这样的: 接受用户的输入 --- 5 个整数 通过 REST 调用网络服务 在服务器端运行一些计算...并生成一个
假设我们有一个名为 configuration.js 的文件,当我们查看内部时,我们会看到: 'use strict'; var profile = { "project": "%Projec
这部分是对 Previous Question 的扩展我的: 我现在可以从我的 CI Controller 成功返回 JSON 数据,它返回: {"results":[{"id":"1","Sourc
有什么有效的方法可以删除 ios 中 CBL 的所有文档存储?我对此有疑问,或者,如果有人知道如何从本质上使该应用程序像刚刚安装一样,那也会非常有帮助。我们正在努力确保我们的注销实际上将应用程序设置为
我有一个 Rails 应用程序,它与其他 Rails 应用程序通信以进行数据插入。我使用 jQuery $.post 方法进行数据插入。对于插入,我的其他 Rails 应用程序显示 200 OK。但在
我正在为服务于发布请求的 API 调用运行单元测试。我正在传递请求正文,并且必须将响应作为帐户数据返回。但我只收到断言错误 注意:数据是从 Azure 中获取的 spec.js const accou
我是一名优秀的程序员,十分优秀!