今天来看一道有意思的链表算法题目。python
给到一个单向链表,要求找出该链表中倒数第 k >个节点,要求只能遍历一次链表,且空间复杂度为 O(1)。算法
思路1:若是能从链表尾部开始遍历,那只需倒序遍历 k 个节点便是要找出的节点,可是因为是单链表,只能从头结点开始遍历。数组
思路2:先遍历一遍该单链表,获取链表的总节点数 n,那么第 n-k+1 这个节点就是倒数第 k 个节点。因此第二次再遍历到第 n-k+1 这个节点便可,可是题目要求只能遍历一遍链表。spa
思路3:经过遍历该链表把节点都存入到一个数组中,而后再经过数组下标可直接获取到倒数第 k 个节点,可是这样会须要额外的存储空间,空间复杂度为 O(n)。指针
上面这三种常规思路其实都是不符合题目要求的,那就只能想其余办法了。code
咱们知道,链表的节点之间都是经过指针来链接的,咱们先额外定义两个空指针,分别叫前指针和后指针。cdn
先让前指针指向链表的头指针并开始遍历,一直遍历到第 k-1 个节点,在这期间,后指针原地保持不动。blog
当前指针遍历到第 k 个节点时,后指针也指向链表头指针并开始遍历,在这以后,前指针每日后遍历一个节点,后指针也日后遍历一个节点。utf-8
这样先后两指针的距离始终都保持为 k-1,当前指针遍历到链表的最后一个节点时,后指针恰好也就到了倒数第 k 个节点了。it
若是还没想明白的话,看下面的图应该就很好理解了。p1 表明前指针,p2 表明后指针,该链表一共有 6 个节点,要求的是倒数第 3 个节点。
固然这只是题目的解决思路,实际用代码来实现这个算法,还有一些须要特别注意的地方。
好比头指针不能为空,k 不能等于 0,k 不能大于链表的总节点数。这些都是须要咱们在代码中考虑到的状况,下面附上一份用 python 实现该算法的代码。
# -*- coding:utf-8 -*-
#链表节点的定义
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindKthToTail(self, head, k):
#若是头指针为空或k为0 直接返回none
if head == None:
return None
if k == 0:
return None
pAhead = pBehind = head
# 快指针先走k步
for i in range(k):
#若是k大于链表长度,返回空
if pAhead == None:
return None
#继续日后遍历
pAhead = pAhead.next
#快慢指针同时日后遍历
while pAhead != None:
pAhead = pAhead.next
pBehind = pBehind.next
return pBehind
复制代码
有问题欢迎留言交流,如文章对你有帮助,就点个赞哈,感谢支持。