原题链接:
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语言趋于一致。