【发布时间】:2018-09-19 20:44:22
【问题描述】:
问题
我正在寻找一种高效的数据结构来执行批量反向、批量交换和随机访问。元素的数量是恒定的。
为了更好地解释我在寻找什么,我将介绍一个定制问题:
我们有 K 个容器,标记为 1, 2, .., K。给定了这些容器的初始排列,并且需要对这个排列进行一些更改,即:一个集合 (block) 的容器可以与另一个块交换,一组可以颠倒,并且在任何时候都应该可以回答位置 i 的容器是什么。
可以通过示例提供更好的解释:
初始排列:(3 4 1 2 7 6 5)
将块 (4 1) 与 (2 7) 交换:(3 2 7 4 1 6 5)
反转块 (7 4 1): (3 2 1 4 7 6 5)
让船只就位(基于 1)3:1
另请注意,所有这些都应该是循环的,例如:
将块 (5 3) 与 (2 1) 交换:(1 5 3 4 7 6 2)
虽然在我提供的示例中,块由其标签标识,但请考虑每个块实际上由起始位置和结束位置标识:
鉴于排列 (1 5 3 4 7 6 2),块 (3 4 7) 由索引(基于 1){3, 5} 标识。
我使用这些标签是为了更清楚地了解这些动作。
我不会对船只和作业的数量做出任何假设或限制,但可能会面临两种主要情况:
- 需要大量随机访问,每组访问一次批量交换和批量反向
- 大量随机访问以及可能的批量交换和反向每次访问
一些想法
解决这个问题的一个想法可能是使用treap 来执行log(n) 交换、惰性传播批量恢复和访问。当然,有一些问题要保持树平衡,但它们是可以解决的。
另一种方法可能是使用双链表来执行常量交换和常量反向操作,但这可能吗?
假设所有查询都在顺序位置上,或者可以使用额外的内存来存储指针或类似的东西以在类似列表的数据结构中提供随机访问,以某种方式可以提供恒定时间交换和恒定的时间倒退?
希望找到更好的临时解决方案:
假设每个move的结构如下:
- 取两个区间(相邻,例如从 (1 2 3 4 5) 取 (1 2) 和 (3 4))
- 最终交换两者
- 最终反转一个或两个,但没有重叠! (例如,交换 (1 2),但不是 (2 3) 或 (5 1),这不是所选间隔之一)
- 重复 1
可能的动作是:
- 交换两个区间
- 颠倒两个间隔但不交换
- 交换两个区间,只反转一个
【问题讨论】:
-
我认为您的操作类似于遗传算法或类似启发式的变异和交叉操作。这是真的吗? @hexa_brian
-
@kurag 实际上,您肯定可以将其视为类似的东西。一般来说,它是对 tsp 实例的启发式(3-opt)
-
您没有提到您的programmin语言,但通常使用数组类型结构。
-
@kurag 这意味着线性反向和交换操作,我们不能做得更好吗?例如使用 Treap。
标签: list optimization data-structures tree