【问题标题】:Rearrange a LinkedList, producing endless end points重新排列 LinkedList,产生无穷无尽的端点
【发布时间】:2020-12-18 03:27:19
【问题描述】:

我现在正在处理重新排列链接列表的问题。代码的逻辑感觉是对的,但是遇到重复链表的无穷无尽的点。我不知道为什么,但感觉更可能是链表的定义有问题。问题是:

给定一个单链表的头部,写一个方法来修改 LinkedList 使得来自 LinkedList 后半部分的节点 从前半部分反向交替插入节点 命令。所以如果 LinkedList 有节点 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> null,你的方法应该返回 1 -> 6 -> 2 -> 5 -> 3 -> 4 -> null。

您的算法不应使用任何额外的空间和输入 LinkedList 应该就地修改。

示例 1:

输入:2 -> 4 -> 6 -> 8 -> 10 -> 12 -> null 输出:2 -> 12 -> 4 -> 10 -> 6 -> 8 -> 空

示例 2:

输入:2 -> 4 -> 6 -> 8 -> 10 -> null 输出:2 -> 10 -> 4 -> 8 -> 6 -> 空

我的做法是:

def rearrange_linkedlist(head):
    # find the middle as the separating point
    middle = middle_linkedlist(head)
    # reverse the second part
    second_head = reverse_linkedlist(middle)
    while head and second_head:
        following_1 = head.next 
        following_2 = second_head.next 
        head.next = second_head
        second_head.next = following_1
        head = following_1
        second_head = following_2

def middle_linkedlist(head):
    slow, fast = head, head 
    while fast and fast.next:
        slow = slow.next 
        fast = fast.next.next 
    return slow

def reserve_linkedlist(head):
    current = head 
    previous = None
    while current:
        following = current.next
        current.next = previous
        previous = current 
        current = following 
    return previous

链表的设置:

from __future__ import print_function

class node:
    def __init__(self, value, next=None):
        self.value = value
        self.next = next 
    
    def print_list(self):
        temp = self
        while temp:
            print(str(temp.value) + ' ', end='')
            temp = temp.next 
        print()

def main():
    head = node(2)
    head.next = node(4)
    head.next.next = node(6)
    head.next.next.next = node(8)
    head.next.next.next.next = node(10)
    head.next.next.next.next.next = node(12)
    rearrange_linkedlist(head)
    head.print_list()
    
main()

结果是:

2 12 4 10 6 8 8 8 

重复 8。我不确定它有什么问题。提前感谢您的帮助。

【问题讨论】:

  • 每当更新一对链接时,添加一个断言以确保它们不是同一个链接。
  • 我不确定这是否是问题所在。在代码的交错部分期间,前半部分的最后一项仍指向后半部分。当它指向中间时,您已到达列表前面的末尾。
  • 谢谢,@RaymondHettinger。这些问题要求空间复杂度为 O(1),所以我更新了链表。您介意解释一下关于断言的更多信息吗?
  • 谢谢,@FrankYellin。我认为你很接近。由于我将链表反转到位,因此两个链表指向相同的尾部,然后指向无。但是我不确定为什么第一个链表会变得无穷无尽,或者没有结尾。请分享更多见解。

标签: python linked-list


【解决方案1】:

将所有三个步骤拆分为不同的辅助函数可能会有所帮助。即,目前,您只有一个帮助函数来查找中间和反转列表。您可能还应该有一个用于合并两个列表(这是您当前代码中的问题所在):

def rearrange_linkedlist(head):
    middle = find_middle(head)
    reversed_second_half = reverse_list(middle)
    merge_two_lists_inplace(head, reversed_second_half)


def find_middle(head):
    fast = slow = head
    while fast and fast.next:
        fast = fast.next.next
        slow = slow.next
    return slow


def reverse_list(head):
    prev, curr = None, head
    while curr:
        curr.next, prev, curr = prev, curr, curr.next  
    return prev


def merge_two_lists_inplace(l1, l2):
    while l1 and l2 and l2.next:
        l1.next, l1 = l2, l1.next
        l2.next, l2 = l1, l2.next

您的代码的问题是链表前半部分的末尾指向反向后半部分的末尾。在合并循环的最后一次迭代中,列表如下所示:

2 -> 12 -> 4 -> 10 -> 6 -> 8 -> null
                      ^    ^
                     head  second_head

当您分配second_head.next = following_1 时,您实际上是在分配最终节点指向它自己。在循环条件中检查 second_head.next 会在循环处于上述状态时终止循环。

【讨论】:

  • 感谢您的建议。我已经更新了我的代码,但仍然遇到了类似的问题。
  • 奇怪的是,我用2 -> 4 -> 6 -> 8 -> 10 -> 12 -> null 测试了上面的代码,得到了预期的响应,没有重复的8,即2 -> 12 -> 4 -> 10 -> 6 -> 8 -> null。您使用的是什么输入失败了?
  • 我更新了我的代码以包含我如何设置链接列表。谢谢你的帮助。节日快乐!
  • 我不确定 l2.next 是否在您的 merge_two_lists_inplace 函数中不是 None 会产生一些影响。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-09
  • 2019-09-18
  • 1970-01-01
  • 1970-01-01
  • 2013-09-23
相关资源
最近更新 更多