剑指 Offer(15)——链表中倒数第k个节点

99 阅读2分钟

这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战

题目 输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

解法 快指针先走k,慢指针再走,快指针到头,慢指针正好倒数k,此时返回慢指针即为所求。

求链表的倒数第K个节点:主要思路设置两个指针,刚开始都指向链表的第一个节点,第一个指针先走k-1步,然后两个一块走,直到第一个指针的下一位为nullptr,则第二个指针所指的位置就是倒数第k个节点。

  在编程书上看见这个方法,自己画了个链表试了试果然是这样,但是这是个什么原理呢?

  想了想是这样的耶。。。

分为两种情况:1、倒数第k个位置在正数第k个位置之后,如图:

  

    此种情况下:P_head和nullptr分别表示链表的头位置和末位置,+k表示正数第K个位置,-K表示倒数第K个位置,first指针代表已经走了K-1个位置之后的第一个指针位置,second表示第二个指针从起始位置开始。

    然后first和second一块开始走,直到first->next指向nullptr,即first_end的位置,此时second走到second_end,second_end即是倒数第k个位置。first和second走过的长度都是蓝色区域加黄色区域的长度。

      2、倒数第K个位置在正数第K个位置之前,如图:

      

    此种情况下:P_head和nullptr分别表示链表的头位置和末位置,+k表示正数第K个位置,-K表示倒数第K个位置,first指针代表已经走了K-1个位置之后的第一个指针位置,second表示第二个指针从起始位置开始。

     然后first和second一块开始走,直到first->next指向nullptr,即first_end的位置,此时second走到 second_end,second_end即是倒数第k个位置。first和second走过的长度都是黄色区域的长度。

 

其实还有第三种情况:就是比较特殊的-k=+k的情况,即倒数第k个位置就是正数第k个位置(中间位置),但这种情况可以归类为以上两种情况的任意一种,不做特殊处理。 代码

//快指针先走k,慢指针再走,快指针到头,慢指针正好倒数k,此时返回慢指针即为所求。
var getKthFromEnd = function(head, k) {
    var fast = head;
    var slow = head;
    while(k) {
        fast = fast.next
        k--
    }
    while(fast != null) {
        fast = fast.next;
        slow = slow.next;

    }
    return slow
}