【问题标题】:How to interact head of linkedlist outside the LinkedList class in Python?如何在 Python 中的 LinkedList 类之外交互链表的头部?
【发布时间】:2021-05-21 06:58:15
【问题描述】:

我正在尝试解决algoexpert 上的以下问题:

移位链表

编写一个函数,接收单链表的头部和一个整数 k,将列表移动到位(即,不创建全新的 list) by k 位置,并返回其新头部。

移动链表意味着向前或向后移动其节点并换行 他们在适当的地方围绕列表。例如,移动链表 向前移动一个位置会使它的尾巴成为链接的新头 列表。

节点是向前还是向后移动取决于是否 k 是正数还是负数。

每个LinkedList 节点都有一个整数value 以及 next 节点指向列表中的下一个节点或 None / null 如果它是列表的尾部。

你可以假设输入的链表总是至少有一个节点; 换句话说,头部永远不会是None / null

示例输入

head = 0 -> 1 -> 2 -> 3 -> 4 -> 5 // the head node with value 0
k = 2

样本输出

4 -> 5 -> 0 -> 1 -> 2 -> 3 // the new head node with value 4

问题给出的代码大纲如下:

class LinkedList:
    def __init__(self, value):
        self.value = value
        self.next = None

def shiftLinkedList(head, k):
    #Write your code here.
    pass

我想我在链表上的背景非常有限,因为从我读过的链表上的每一个资源来看,它的概要都需要节点类,并且在 LinkedList 类中拥有所有旋转或移动的方法.

我假设函数的 head 参数将是一个表示列表位置的整数,但是我如何将 head 引用回原始列表?我已经在 Thonny 编辑器中编写了代码,但我在 LinkedList 类中编写了函数,并在列出我的列表后简单地调用它。

例如:

class Node:
    def __init__self(data):
        self.data = data
        self.next = None

class LinkedList:
    def __init__(self):
        self.head = None
    def push(self, newhead):
        newnode = Node(new_data)
        newnode.next = self.head 

        self.head = newnode


 list1 = LinkedList()
 list1.head = Node(1)
 e2 = 2
 e3 = 3

 list1.head.next = e2
 e2.next = e3 

只有在我建立了我的链表后,我才能在类中创建一个方法来移动或旋转它。还是我错了?

我尝试按照算法想要的方式创建一个函数,但我仍然卡住了。我想我真正困惑的是参数head是整数还是LinkedList

这是我的完整尝试:

class Node:
    def __init__(self, data):
        self.data = data #assign data
        self.next = None #initialize next as null
        

class LinkedList:
    #function to initalize the linked list object
    def __init__(self):
        self.head = None
        
    def printList(self):
        temp = self.head
        while(temp):
            print(temp.data)
            temp = temp.next
            
    def moveToFront(self):
        tmp = self.head
        sec_last = None
        if not tmp or not tmp.next:
            return
        
        while tmp and tmp.next:
            sec_last = tmp
            tmp = tmp.next
        
        sec_last.next = None
        tmp.next = self.head
        self.head = tmp
        


def shiftList(head, k):
    if not head:
        return
    tmp = head
    length = 1
    while(temp.next != None):
        tmp = tmp.next
        length += 1
        
    if(k>length):
        k = k%length
    
    k = length - k
    
    
    if(k==0 or k==length):
        return head
    current = head
    cmt = 1
    while(cmt < k and current != None):
        current = current.next
        cmt += 1
    
    if(current==None):
        return head
    kthnode = current
    tmp.next = head
    head = kthnode.next
    kthnode.next = None
    return head

【问题讨论】:

    标签: python data-structures linked-list


    【解决方案1】:

    我假设函数的 head 参数将是一个表示列表位置的整数

    不,列表的头部是LinkedList 实例。所以head.value是列表中第一个节点的值,head.next是对列表中第二个节点的引用。

    在您的尝试中,您更改了 LinkedList 的原始定义,并创建了另一个名为 Node 的类,这实际上是 LinkedList 应该是的(除了您调用属性 data而不是value)。您这样做是可以理解的,因为您希望为 整个 链表提供一种容器类,并为该列表中的单个节点保留一个单独的类 Node。但是这个代码挑战不适用于这样的容器类。

    它只适用于一个代表节点的类,但通过它的next 成员,整个列表都是从中推断出来的。此外,他们希望函数在移动完成后返回对已成为列表头部的节点的引用。这是与容器类不同的工作方式,在容器类中,您将 mutate head 成员,并且不会返回任何内容:调用者只需通过修改后的 head 访问列表会员。

    因此,您打算做的事情本身并没有错,只是这个代码挑战正在使用的数据结构不是。你应该接受它。

    我真正困惑的是参数“head”是整数还是链表

    它是一个节点,但列表是从中推断出来的。他们称他们的班级为LinkedList 而不是Node 可能有点令人困惑,但这取决于你如何看待它。

    所以你可以这样解决它:

    • 首先找出列表中的最后一个节点。为此,您必须从头开始(您没有别的东西)并逐步浏览列表,直到碰到它的结尾。还要维护一个计数器,以便最后知道列表中有多少个节点。
    • 然后创建一个从尾节点到头节点的链接,这样列表现在就变成了循环:它没有尽头了
    • 找出哪个节点在此循环列表中的尾节点之前 步。由于不可能在列表中向后走,因此您实际上应该向前走 size-k 步,因此您需要在第一步中确定的列表大小。
    • 找到节点之后的节点应该成为头节点。
    • 使该节点本身成为新的尾节点:断开它与其后的节点(新的头)之间的链接。
    • 返回新的头部引用

    还应采取措施保护此代码免受 k巨大 值的影响。假设列表有 6 个元素,而 k 是 600,那么循环列表运行 600 次当然是没有意义的,因为我们可以预测你会从开始的地方结束! 600 是 6 的倍数...因此,为了提高效率,您需要将 k 减少到小于列表大小的数字。知道您需要向前迈出多少步的公式是-k % size

    下面是这个想法的实现:

    def shiftLinkedList(head, k):
        if not head:
            return  # Nothing to do
        # Determine size of the list, and its tail node
        size = 1
        tail = head
        while tail.next:
            size += 1
            tail = tail.next
        
        # Temporarily make the list cyclic
        tail.next = head
        # Find out where to cut the cycle
        for _ in range(-k % size):
            tail = tail.next
        head = tail.next
        # Cut the cycle
        tail.next = None
        return head
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-29
      • 1970-01-01
      • 1970-01-01
      • 2019-01-28
      • 1970-01-01
      相关资源
      最近更新 更多