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

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

  想了想是这样的耶。。。

分为两种情况:1、倒数第k个位置在正数第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个位置之前,如图:

      求链表中的倒数第K个节点_github_02

    此种情况下: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个位置(中间位置),但这种情况可以归类为以上两种情况的任意一种,不做特殊处理。

 

故可以简单的写出代码:

注意事项:1、要是K大于链表长度怎么办?

     2、k<=0怎么办?

 



1 ListNode* FindR_Kth(ListNode* p_head, unsigned int k)
2 {//找到链表的倒数第K个节点
3 //if (k==0)特殊处理
4 //k小于链表长度,特殊处理
5 if (p_head = nullptr)
6 return nullptr;
7 ListNode* first = p_head;
8 ListNode* second = p_head;
9 for (int i = 0; i < k - 1; i++)
10 {
11 first = first->next;
12 }
13 while (first->next != nullptr)
14 {
15 first = first->next;
16 second = second->next;
17 }
18 return second;
19 }


 


 最终的完善:



 

1 struct ListNode{
2 int value;
3 ListNode* next;
4 };
5 ListNode* findKthToTail(ListNode *phead,unsigned int k)
6 {
7 if (k == 0)/
8 return nullptr;
9 if (phead == nullptr)
10 return nullptr;
11 ListNode *p1 = phead;
12 ListNode *p2 = phead;
13 for (int i = 1; i < k; ++i)
14 {
15 if (p1->next == nullptr){//若k比本身链表的最大长度还大则直接返回nullptr
16 return nullptr;
17 }
18 p1 = p1->next;
19 }
20 while (p1->next != nullptr)
21 {
22 p1 = p1->next;
23 p2 = p2 ->next;
24 }
25 return p2;
26 }


 




作者:柒月