“这是我参与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
}