leetCode刷题 19. 删除链表的倒数第N个节点

1,277 阅读3分钟

原题链接:

https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/description/

题目描述

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.

说明

给定的 n 保证是有效的。

进阶

你能尝试使用一趟扫描实现吗?

题目解析:

如果不考虑进阶的要求的话,是一道很简单的题目。只需要找出要删除的节点的位置,然后进行删除操作就可以了。

需要做题者熟悉链表结构和链表的遍历。

思路

思路一:

不考虑进阶中的只遍历一次的要求,很简单。先完整遍历一次链表,得出链表长度,然后根据题目给出的n,就可以知道需要删除的节点的位置。再次从头遍历链表就可以进行操作得出结果。

思路二:

快慢指针。快指针一次走两步,慢指针一次走一步。两个指针同时出发,当快指针走到表尾时,慢指针刚好走到中间的位置(链表长度奇数的话慢指针刚好在中间,偶数的话在中间往后一个位置)。此时可以根据链表的长度和题目给出的n得出要删除的节点的位置。如果在慢指针之前,则从头开始遍历。如果在慢指针之后,则从慢指针位置向后遍历。这样可以实现一次扫描得出结果。

思路三(推荐):

使用前后指针。前指针先走n步。然后前指针和后指针同时走,当前指针走到表尾时,后指针刚好走到要删除的元素的位置。这样可以实现一次扫描得出结果,而且比思路二简单。

代码(Python2)

思路一代码

    #两次遍历,先遍历出长度,再删除
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        #链表长度
        length = 0
        currentNode = head
        #遍历一次,得出链表长度
        while (currentNode):
            length += 1
            print "currentNode=",currentNode.val
            currentNode = currentNode.next
        
        #算出要删除元素的位置(从0开始计算)
        index = length - n
        currentNode = head
        print "length=",length
        print "index=",index
        
        #如果要删除的是第一个元素
        if index == 0:
            return currentNode.next
        
        #删除元素
        for i in range(length):
            print "currentNode1=",currentNode.val
            #遍历到要删除元素的前一个元素
            if i == index-1:
                currentNode.next = currentNode.next.next
                return head
            else:
                #继续遍历
                currentNode = currentNode.next

思路2代码:

    #使用快慢指针计算出长度,然后慢指针从两边走
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        #快慢指针
        fastNode = head
        slowNode = head
        
        #初始化
        length = 0
        slowIndex = 0
        fastIndex = 0
        
        #遍历快慢指针,得出length。此时的slowNode就是中间位置
        while(True):
            
            if fastNode == None:
                #偶数个
                length = fastIndex
                break
            elif fastNode.next == None:
                #奇数个
                length = fastIndex + 1
                break
            else:
            
                #快慢指针遍历
                fastNode = fastNode.next.next
                slowNode = slowNode.next
            
                fastIndex += 2
                slowIndex += 1
        
        #得出要删除的节点的位置
        index = length - n
        
        print "length=",length
        print "index=",index
        print "slowIndex=",slowIndex
        
        currentNode = head
        
        #如果要删除的是第一个元素
        if index == 0:
            return head.next
        
        #要删除的元素在slowIndex之前,从头开始遍历
        if index <= slowIndex:
            for i in range(index):
                #遍历到要删除元素的前一个元素
                if i == index-1:
                    currentNode.next = currentNode.next.next
                    return head
                else:
                    #继续遍历
                    currentNode = currentNode.next
        #要删除的元素在slowIndex之后,从slowIndex开始遍历
        elif index > slowIndex:
            index = index - slowIndex
            currentNode = slowNode
            for i in range(index):
                #遍历到要删除元素的前一个元素
                if i == index-1:
                    currentNode.next = currentNode.next.next
                    return head
                else:
                    #继续遍历
                    currentNode = currentNode.next
        else:
            return head

思路三代码(推荐):

def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        #前后指针
        frontNode = head
        behindNode = head
        length = 0
        
        #前指针先走n步
        for i in range(n):
            frontNode = frontNode.next
            length += 1
        print "length = ",length
        print "n = ",n
        
        #代表要删除的是第一个元素
        if frontNode == None:
            return head.next
        
        #前后指针同时走
        while (frontNode.next):
            frontNode = frontNode.next
            behindNode = behindNode.next
            length += 1
        
        print "length = ",length
        
        #删除元素
        behindNode.next = behindNode.next.next
        return head

谦言忘语

个人目前只懂一丁点python语法,所以不做语法上的优化,而且整体代码风格效果会尽量跟C语言趋于一致。