剑指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 };