简体   繁体   English

从链表末尾删除第 k 个节点

[英]remove kth node from end of linked list

I am trying to remove the kth element from the END of a linked list.我正在尝试从链表的END中删除第kth元素。 Here is my code这是我的代码

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


def removeKthNodeFromEnd(head, k):
    if k == 0 or head is None:
        return

    temp = head
    while temp is not None and k > 1:
        temp = temp.next
        k -= 1

    if temp is None or k > 1:
        return head

    trailing = None
    leading = head
    while temp.next is not None:
        trailing = leading
        leading = leading.next
        temp = temp.next

    if trailing is None:
        head = head.next
    else:
        trailing.next = leading.next


head = LinkedList(0)
head.next = LinkedList(1)
head.next.next = LinkedList(2)
head.next.next.next = LinkedList(3)
head.next.next.next.next = LinkedList(4)
head.next.next.next.next.next = LinkedList(5)
head.next.next.next.next.next.next = LinkedList(6)
head.next.next.next.next.next.next.next = LinkedList(7)
head.next.next.next.next.next.next.next.next = LinkedList(8)
head.next.next.next.next.next.next.next.next.next = LinkedList(9)


removeKthNodeFromEnd(head, 10)

while head is not None:
    print(head.value)
    head = head.next

But this does not work and prints out all the values in the linked list from 0 to 9. Why is this the case?但这不起作用并打印出链表中从0到9的所有值。为什么会这样? If the node to delete is the head node which I check by checking trailing is None , then I update head = head.next .如果要删除的节点是我通过检查trailing is None ,那么我更新head = head.next I am changing head to be the next node.我正在改变head成为下一个节点。 I can return head after this update and the result of head = removeKthNodeFromEnd(head, k) will give me the desired output but why can't I do it the other way without returning anything?我可以在此更新后返回head并且head = removeKthNodeFromEnd(head, k)的结果将为我提供所需的输出,但为什么我不能以其他方式执行而不返回任何内容? For instance in my solution I can get rid of any element in between the first and last node including the last and works just fine.例如,在我的解决方案中,我可以去掉第一个节点和最后一个节点之间的任何元素,包括最后一个节点,并且工作得很好。 The original head gets updated and node gets removed.原始头得到更新,节点被删除。 But when trying to update the head node head = head.next it does not work.但是当尝试更新头节点head = head.next时,它不起作用。

One way I achieved this is by doing the following...我实现这一目标的一种方法是执行以下操作...

if trailing is None:
  head.value = head.next.value
  head.next = head.next.next

But why must I use the values?但是为什么我必须使用这些值? To me this seems the same as对我来说,这似乎与

if trailing is None:
  head = head.next
  head.next = head.next.next

but does not work但不起作用

It doesn't work because head in that function is a local name.它不起作用,因为该函数中的head本地名称。 Assigning to a local variable never does anything to other variables, even not when they happen to have the same name (like the global head ).分配给局部变量永远不会对其他变量做任何事情,即使它们碰巧具有相同的名称(如全局head )。

The "trick" you have by moving a linked list value with head.value = head.next.value will not work when the list only has one node.当列表只有一个节点时,使用head.value = head.next.value移动链表值的“技巧”将不起作用。

One way to do this, is to return the (potentially modified) value of head , and expect the caller to assign this back to their own head variable.一种方法是返回head的(可能修改的)值,并期望调用者将其分配回他们自己的head变量。

So:所以:

  • in removeKthNodeFromEnd make sure all return statements are like return head , and that you add a return head at the very end.removeKthNodeFromEnd确保所有return语句都像return head ,并在最后添加一个return head In short, removeKthNodeFromEnd should always return head .简而言之, removeKthNodeFromEnd应该总是返回head

  • in the main program, change the call to head = removeKthNodeFromEnd(head, 10)在主程序中,将调用改为head = removeKthNodeFromEnd(head, 10)

That will solve your issue.这将解决您的问题。

Here are some ideas to make your code more elegant:这里有一些想法可以让你的代码更优雅:

  • Create a separate class for maintaining the head of the linked list创建一个单独的类来维护链表的头部
  • Improve the constructor, so that it is easier to initialise a linked list改进构造函数,使初始化链表更容易
  • Add an iterator so it is easier to print a linked list添加迭代器,以便更容易打印链表
class Node:  # renamed
    def __init__(self, value, nxt=None):
        self.value = value
        self.next = nxt  # is now an argument


class LinkedList:  # added
    def __init__(self, *values):
        self.head = None
        if values:  # populate the list with values
            for value in reversed(values):
                self.push_front(value)

    def push_front(self, value):
        self.head = Node(value, self.head)

    def __iter__(self):
        node = self.head
        while node:
            yield node.value
            node = node.next
    
    def removeKthNodeFromEnd(self, k):
        if k <= 0:
            return
        temp = self.head
        for _ in range(k):
            if not temp:  # k is out of range
                return
            temp = temp.next

        if temp:
            trailing = self.head
            while temp.next:
                trailing = trailing.next
                temp = temp.next
            trailing.next = trailing.next.next
        else:
            self.head = self.head.next
    

lst = LinkedList(*range(10))
print(*lst)
lst.removeKthNodeFromEnd(0)
print(*lst)

And if you maintain a size attribute, you can do:如果你维护一个size属性,你可以这样做:

class LinkedList:  # added
    def __init__(self, *values):
        self.head = None
        self.size = 0
        if values:
            for value in reversed(values):
                self.push_front(value)

    def push_front(self, value):
        self.head = Node(value, self.head)
        self.size += 1

    def __iter__(self):
        node = self.head
        while node:
            yield node.value
            node = node.next

    def removeAt(self, k):
        if 1 < k <= self.size:
            trailing = self.head
            for _ in range(k - 2):
                trailing = trailing.next
            trailing.next = trailing.next.next
        elif 1 == k <= self.size:
            self.head = self.head.next
    
    def removeKthNodeFromEnd(self, k):
        self.removeAt(self.size + 1 - k)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM