重新排列链表。给定一个链表a1 a2 ... a b1 b2 ... bn重新排列为a1 b1 a2 b2 ... a bn。

时间:2013-09-10 04:59:31

标签: algorithm

最近我阅读了破解代码,在第2章中介绍了解决多数链表问题的runner方法。

给定一个链表a1 a2 ... a b1 b2 ... bn重新排列为a1 b1 a2 b2 ... a bn。

它说我们应该使用两个跑步者,速度更快的跑步者应该跑得慢一倍。

因为它总数是偶数,所以当结束时跑得更快时,链接列表中间的速度就越慢。然后将较快的跑步者放在链接列表的开头,并插入较慢的跑步者之后较慢的指向的元素。

我知道这个原则,但我的问题是:

例如

1 2 3 4 1 2 3 4

首先,两位选手都指向“1”,

然后较快的跑步者指向“3”,较慢的指向“2”。

越快的乐趣者指向第二个“1”,越慢指向“3”。

较快的跑步者指向第二个“3”,较慢的指向“4”。

然后呢?我该怎么办?我不能把速度更快的跑者放到第一个“1”,因为我还没有到达链表的末尾。与较慢的一样,它没有到达链表的中间。

如果我在链接列表中添加头部,则较快的跑步者和较慢的跑步者可以到达中间和结束。我的意思是它看起来如下:

0 1 2 3 4 1 2 3 4;

所以我想知道,如果我想使用runner方法来解决这个问题,我应该为快跑者和慢跑者添加一个索引吗?

2 个答案:

答案 0 :(得分:1)

# This is a testing function by Pengyu CHEN (cpy.prefers.you[at]gmail.com)
# For answering questions on StackOverflow.com
# COPYLEFT, ALL WRONGS RESERVED.

"""
To rearrange a lst from a_1->a_2->...->a_n->b_1->b_2->...->b_n
to a_1->b_1->...->a_i->b_i->...->a_n->b_n
"""
def linked_list_rearrange(lst):
    # step 1:
    fast = lst.head
    slow = lst.head
    while fast != None:
        fast = fast.next
        fast = fast.next # assuming here it won't generage any errors
        slow = slow.next
    # step 2:
    fast = lst.head
    # now slow is at middle of the list, means b_1
    while slow != None:
        temp = slow.next
        slow.next = fast.next
        fast.next = slow
        fast = slow.next
        slow = temp
    return lst

假设您是一名翻译并将输入列表提供给上述功能。通过遵循其步骤,您可以清楚地了解我认为的算法。

更新:修正:从fase到fast的拼写错误 更新:已添加:copyright(copyleft)信息。

答案 1 :(得分:0)

以编程方式思考。当它表示速度提高两倍时,它意味着在一次迭代中,它需要一步,然后由另一步完成。

所以在the faster runner points to the second "3", the slower points to the "4".之后,较慢的移动到第二个“1”,而较快的第一个移动到第二个“4”。如果节点(更快指向的节点)指向NULL(或者如果它是列表中的最后一个节点),则需要更快地检查移动,更快地移动到列表中的第一个节点。

然后,只需将当前较慢的节点(第二个“1”)移动到当前指向较快的节点(第一个“1”)之后。

HTH