https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/comments/
对于链表类题目,对某一个特定索引的元素进行操作往往会成为增加运算时间的瓶颈,因此如何通过尽可能少的遍历次数寻找到所要操作的元素就成为关键。
比如这道题,由于我们不知道链表的长度,并且只能从头部开始遍历,假设我们不运用任何技巧,两次遍历可以解决这个问题。
第一次遍历可以得知链表的长度L,第二次遍历从头找到L-n位置的链表元素,删除即可。
两次遍历,时间复杂度为O(n), 空间复杂度O(1)。
能不能用1次遍历解决这个问题呢?这里我们运用到解决这类线性列表的数据结构题目一个高频技巧,双指针。
为了方便,我们在原有链表前面设置一个哑结点,哑结点的好处在于,因为这里我们是要删除一个结点,所以我们可以定位到被删除结点的前置结点,然后将前置结点的后续指针指向被删除结点的后续结点,则可完成删除。
我们设置两个指针,两个指针初始状态都指向哑结点,指针fast 先走n步,然后指针fast和指针slow同步往前继续遍历链表,直至fast的后续结点为空,此时指针slow到达被删除结点的前置结点。
下面这个视频解释了这个过程:
超可爱!动画教你如何删除链表的倒数第n个结点
代码:
# Definition for singly-linked list.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
if not head:
return head
slownode = ListNode(None)
slownode.next = head
fastnode = slownode
for i in range(n):
fastnode = fastnode.next
while(fastnode.next!=None):
slownode = slownode.next
fastnode = fastnode.next
if slownode.next == head:
head = head.next
else:
slownode.next = slownode.next.next
return head
时间复杂度为O(n), 空间复杂度O(1)。
喜欢就点个赞吧~