前几天我出去买杂货,需要搜索我的钱包,找到我的信用卡,我的客户奖励(忠诚度)卡和我的带照片的身份证。我的钱包里有几十张其他卡片(工作证,其他信用卡等),所以我花了一些时间找到所有东西。
我的钱包里面有六个插槽,我可以放卡片,每个插槽中只有第一张卡片最初可以看到。如果我想找到一张特定的卡片,我必须记住它所在的插槽,然后一次查看该插槽中的所有卡片以找到它。它离插槽前面越近,就越容易找到它。
我想到这几乎是一个数据结构问题。假设您有一个由k个链表组成的数据结构,每个链表都可以存储任意数量的元素。您希望以最小化查找的方式将元素分发到链接列表中。您可以使用任何系统将元素分发到不同的列表中,并可以随时重新排序列表。鉴于这种设置,在任何假设下都有一种最佳的订单排序方式:
我在钱包中使用的非正式系统是根据用例(ID,信用卡,会员卡等)将卡“哈希”到不同的插槽中,然后将每个插槽中的元素按访问频率粗略排序。但是,也许有更好的方法(例如,无论用例如何,都将k个最常用的元素存储在每个插槽的前面)。
是否有已知的解决此问题的系统?这是数据结构中众所周知的问题吗?如果是这样,最佳解决方案是什么?
(如果这似乎与编程无关:我可以想象一个应用程序,其中用户有几个常用项目的下拉列表,并希望以最小化时间的方式保留这些项目需要找到一个特定的项目。)
答案 0 :(得分:3)
虽然不是一般k的完整答案,this 1985 paper by Sleator and Tarjan给出了对k = 1情况下几种动态列表更新算法的摊销复杂性的有用分析。事实证明前移是非常好的:假设每个项目的固定访问概率,它永远不需要超过最优步骤所需的步数(移动和交换)的两倍(静态)算法,其中所有元素都以非递增的概率顺序列出。
有趣的是,其他一些合理的启发式方法 - 即在找到所需元素后与前一个元素进行交换,并根据显式频率计数维持顺序 - 不会共享这种理想的属性。 OTOH,第2页。 2他们提到Rivest的早期论文表明,在以前交换的任何访问的预期摊销成本是< =移动到前面的相应成本。
我只阅读了前几页,但它看起来与我有关。希望它有所帮助!
答案 1 :(得分:0)
您需要查看跳过列表。对于有快车和普通列车的列车系统安排车站存在类似的问题。特快列车仅在快车站停靠,而普通列车则在常规车站和快车站停靠。快速停靠点应放在何处,以便从起始站到任何车站时,可以最大限度地减少平均停靠次数。
解决方案是使用三元数的站(即1,3,3,10等处,其中T_n = n *(n + 1)/ 2)。
这假设所有止损(或卡)都可能被访问。
答案 2 :(得分:0)
如果您事先知道n张卡的访问概率并且您有k个钱包插槽并且访问是独立的,那么贪婪的解决方案是否最佳是不是很明显?也就是说,最常访问的k卡位于口袋的前面,最常访问的k卡立即落后,依此类推? (你从不希望在概率较高的卡之前排名较低概率的卡。)
如果您不知道访问概率,但是您确实知道它们存在并且卡访问是独立的,我想象类似地对卡进行排序,但是通过访问次数 - 看得那么远 - 而不是渐近最优。 (向前移动也很酷,但我没有看到明显的理由在这里使用它。)
如果你惩罚卡片动作,也许你会得到一些有趣的东西;如果我在卡访问上有任何已知的概率分布,无论是否独立,我每次访问时都会贪婪地重新排序。