【发布时间】:2010-04-17 08:19:53
【问题描述】:
我正在努力解决这个问题:
https://www.spoj.pl/problems/CERC07S/
我已经确定我需要一个数据结构,其中逆向操作的时间复杂度较低。我尝试使用双向链表创建一个,其中(我认为)只需更改与指示遍历列表方向的开始和结束节点关联的值,就可以在 O(1) 中完成反转。我试图实现它但被卡住了。可能方法不对!
树在这里适用吗?如果是,如何?任何想法或链接表示赞赏?
提前致谢。
【问题讨论】:
我正在努力解决这个问题:
https://www.spoj.pl/problems/CERC07S/
我已经确定我需要一个数据结构,其中逆向操作的时间复杂度较低。我尝试使用双向链表创建一个,其中(我认为)只需更改与指示遍历列表方向的开始和结束节点关联的值,就可以在 O(1) 中完成反转。我试图实现它但被卡住了。可能方法不对!
树在这里适用吗?如果是,如何?任何想法或链接表示赞赏?
提前致谢。
【问题讨论】:
我同意双向链表。这是实现它的一种方法。
对于每个节点,将两个指针作为一个数组。在节点中也有数字的值和一个布尔变量 dir。最初,将每个节点中的第一个指针指向前一个节点,将第二个指针指向下一个节点,并将所有节点的 dir 设置为 0。在遍历链表时,跟踪具有方向 D 的变量. 首先设置为1。它指示要遵循哪个指针才能到达每个节点的下一个元素。当你到达一个节点时,如果dir设置为1,则将D设置为D的NOT,并继续使用D查找下一个节点。
要反转节点序列,将dir设置为要反转的节点序列的最后一个节点和最后一个节点之后的节点的非,将序列之前节点的正确指针指向序列的最后一个元素(反之亦然),并将序列后节点的正确指针指向序列的第一个元素(反之亦然)。
希望这能让您对至少一种前进方式有所了解。
【讨论】:
这是伪装的Selection sort。您对使用双向链表进行 O(1) 反转是正确的。 (不要对列表进入另一个列表感到困惑。您可以删除要反转的子列表,反转并重新插入它,所有这些都在 O(1) 中,或者任何使您的代码更简单的方法)。
我知道这只是一个练习,但可以注意到反转并不重要,重要的是交换第一个和最后一个元素。这就是维持不变的at step i, the list up to position i is sorted 所需要的一切。对于较大的 i,列表包含的顺序未定义。如果你颠倒一个未定义的顺序,你所拥有的仍然是一个未定义的顺序:)
【讨论】:
实际上,Dimitris 对这个算法的真正含义是正确的。也就是说,考虑到问题确实需要您执行反转,双向链表是合适的。你在 O(1) 中倒车是对的。可能让你陷入困境的是这部分:
[我认为]只需更改与开始和结束节点关联的值,就可以在 O(1) 中完成反转...
诀窍不是专门对节点做任何事情,而是对列表本身(即封装列表结构的对象);更改其状态以便进行迭代,它从其 last 节点开始并从那里向后退。如果要维护列表的可变性(在此示例中不相关),您还将使此状态负责确保以前声称将节点添加到列表的 end 的方法将它们添加到“开始”(新结束),反之亦然。直观地说,这个“状态”实际上只是一个简单的二进制开关,指示列表是否反转。
【讨论】: