【问题标题】:Efficiently searching a doubly-linked list for a value with a pointer constraint?有效地在双向链表中搜索具有指针约束的值?
【发布时间】:2014-04-12 21:07:57
【问题描述】:

这个问题已经给我解决了:

假设你有一个双向链表和一个指向该列表中某个元素的指针。假设您想在列表中搜索某个值 v,您知道该值存在于某处。不使用除 p 之外的其他指针,设计一个 Θ(m) 时间的算法来寻找 v,其中 m 是 p 和包含 v 的节点之间的距离。不要修改输入列表。

有没有人知道如何解决这个问题?我能想到的唯一方法是破坏性地修改列表。

【问题讨论】:

  • @Dukeling 你能说得更具体点吗?怎么会很简单?
  • @FilipeGonçalves 添加了答案。

标签: algorithm data-structures linked-list time-complexity


【解决方案1】:

作为提示:如果您向前走一步、向后走两步、向前走四步、向后走八步等会发生什么?找到元素总共需要多少步?

在进行分析时,您可能会发现对几何级数求和很有用。如果有帮助, 1 + r + r2 + r3 + ... + rn-1 = (rn - 1) / (r - 1).

希望这会有所帮助!

【讨论】:

  • 如何只用一个指针同时前进和后退?
  • @Genadi 抱歉,我最初的回答没有奏效。我已经更新了答案以给出不同的提示。
  • 谢谢,我想过这个问题,但我认为在最坏的情况下(算术级数)需要 m^2,因为你必须前进一、二后、三前、四后等。和你描述的不完全一样。
  • @Genadi 如果您使用算术级数(前进一步,后退两步,前进三步,后退四步等),您说得对,它需要时间 m^2。但是,尝试使用几何级数:向前 2^0、向后 2^1、向前 2^2、向后 2^3、向前 2^4 等等,看看会发生什么。
  • 我认为这种方式会遗漏一些未访问的节点。
【解决方案2】:

我认为templatetypedef has the correct answer,但基于问题的原始措辞,我想到了以下解决方案,它指出列表不能“破坏或改组”,这可能意味着修改它是可以的,如果你可以再改回来——即使这不是真的,我仍然认为这是一个有趣的方法。


用2个指针很容易解决,对吧?一个前进,一个后退,同时移动两者,直到您找到您正在寻找的价值。

现在这一切都很好,除了我们只允许有 1 个指针。

如果你考虑一个双链表,我们知道前一个节点的next 指针只是指向当前元素的指针,所以,如果我们丢失它,我们可以重新设置它。

所以我们可以使用p.prev.next 作为免费存储(和p.prev.prev.next,给出类似的论点)。

所以,我们只能使用一个向前的指针,而将向后的指针存储在p.prev.next 中,并在我们前进时适当地移动它。

一些 Java 风格的伪代码忽略了列表结尾检查,并且为了简单起见没有找到它(我认为它已经足够复杂了):

if p.data == v
  return v

p = p.next
p.prev.next = p.prev.prev

while not found
  if p == v || p.prev.next == v
    p.prev.next = p                   // restore p.prev.next
    return v
  p = p.next
  p.prev.next = p.prev.prev.next.prev // set up p.prev.next from p.prev.prev.next
  p.prev.prev.next = p.prev           // restore p.prev.prev.next

【讨论】:

  • 感谢@Dukeling!这是一个创造性的解决方案!
  • 令人兴奋。 太美了。尽管我会选择 @templatetypedef 答案作为接受,但这是非常非常聪明且绝对天才的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-31
  • 2013-11-15
  • 1970-01-01
  • 1970-01-01
  • 2010-11-11
相关资源
最近更新 更多