剑指offer---链表中倒数第k个结点

问题:链表中倒数第k个结点

要求:输入一个链表,输出该链表中倒数第k个结点。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
    
    }
};

 以下是几种常见的解题思路:

  • 思路一:由于倒数第k元素就是正数第k-1个元素(正数第一个元素索引为0)所以我们首先反转链表,然后遍历前k-1个元素即可解决。但是此方法已经改变链表结构,且相当于遍历两次链表;
  • 思路二:首先求得链表长度n,然后正向遍历n-k即可。但是还是需要两次遍历,因为求得链表长度需要一次完整遍历;
  • 思路三:两指针法:定义两个指针,两指针都指向链表第一个节点,第一个指针从链表头开始遍历,第二个指针保持不动;从第k步开始,第二个指针也开始从链表头开始遍历。知道第一个指针到达尾节点,此方法只需遍历一次,两指针同时进行遍历。【关于思路三的图解,可以参见这里

注意事项:

  • (1)输入链表头指针为空的情况--- return nullptr;
  • (2)k=0的情况--- return nullptr;
  • (3)链表节点数目少于k的情况--- 根据第一个指针判断k是不是大于节点数

 代码:

 1 struct ListNode {
 2     int val;
 3     struct ListNode *next;
 4     ListNode(int x) :
 5             val(x), next(NULL) {
 6     }
 7 };
 8 
 9 class Solution {
10 public:
11     ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
12         if (pListHead == nullptr || k == 0)
13             return nullptr;
14         ListNode *pRight = pListHead;
15         ListNode *pLeft = pListHead;
16         unsigned int index = 0;
17         while(index != k-1){
18             index++;
19             if(pRight->next != nullptr)
20                 pRight = pRight->next;
21             else
22                 return nullptr;
23         }
24         while(pRight->next != nullptr){
25             pRight = pRight->next;
26             pLeft = pLeft->next;
27         }
28         return pLeft;
29     }
30 };
原文地址:https://www.cnblogs.com/iwangzhengchao/p/9774774.html