找出链表中倒数第K个节点

今天来看一道有意思的链表算法题目。

给到一个单向链表,要求找出该链表中倒数第 k 个节点,要求只能遍历一次链表,且空间复杂度为 O(1)。

思路1:如果能从链表尾部开始遍历,那只需倒序遍历 k 个节点即是要找出的节点,但是由于是单链表,只能从头结点开始遍历。

思路2:先遍历一遍该单链表,获取链表的总节点数 n,那么第 n-k+1 这个节点就是倒数第 k 个节点。所以第二次再遍历到第 n-k+1 这个节点即可,但是题目要求只能遍历一遍链表。

思路3:通过遍历该链表把节点都存入到一个数组中,然后再通过数组下标可直接获取到倒数第 k 个节点,但是这样会需要额外的存储空间,空间复杂度为 O(n)。

上面这三种常规思路其实都是不符合题目要求的,那就只能想其他办法了。

我们知道,链表的节点之间都是通过指针来连接的,我们先额外定义两个空指针,分别叫前指针和后指针。

先让前指针指向链表的头指针并开始遍历,一直遍历到第 k-1 个节点,在这期间,后指针原地保持不动。

当前指针遍历到第 k 个节点时,后指针也指向链表头指针并开始遍历,在这之后,前指针每往后遍历一个节点,后指针也往后遍历一个节点。

这样前后两指针的距离始终都保持为 k-1,当前指针遍历到链表的最后一个节点时,后指针刚好也就到了倒数第 k 个节点了。

如果还没想明白的话,看下面的图应该就很好理解了。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

有问题欢迎留言交流,如文章对你有帮助,就点个在看哈,感谢支持。

推荐文章:

mysql索引为啥要选择B+树 (下)

找出数组中只出现一次的数

原文发布于微信公众号 - 谭小谭(tanstory)

原文发表时间:2019-03-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券