问题:输入一个链表,输出该链表中倒数第k个结点。
思路1:一个比较笨的方法是遍历链表的节点,统计从当前节点到末尾的节点数,当节点数恰好等于k时,当前节点就是链表中倒数第k个节点。这种方法的时间复杂度是O(n^2),比较坏的情况是:链表很长,且k很小。
C++
/**
* Definition of ListNode
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
while (pListHead) {
if (countNodes(pListHead) == k) return pListHead;
pListHead = pListHead->next;
}
return NULL;
}
int countNodes(ListNode* head) {
int ret = 0;
while (head) {
ret++;
head = head->next;
}
return ret;
}
};
思路2:先遍历一次链表,记下链表的长度len
;第二次遍历链表,走到len-k+1
的位置,就是倒数第k
个节点。
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
int len = 0;
ListNode *cur = pListHead;
while (cur) {
len++;
cur = cur->next;
}
cur = pListHead;
int cnt = 0;
while (cur) {
cnt++;
if (cnt == len-k+1) return cur;
cur = cur->next;
}
return NULL;
}
};
思路3:维护两个指针:主指针mainPtr
和从指针refPtr
,开始都指向链表头部。先将从指针移到第k个节点,然后两个指针同时往前走,当从指针走到最后一个节点时,主指针所处的位置就是链表倒数第k个节点。这个方法比较巧妙,只需遍历一次链表。
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if (!pListHead || k <= 0) return NULL;
ListNode *mainPtr = pListHead, *refPtr = pListHead;
for (int i = 1; i < k; ++i) {
refPtr = refPtr->next;
if (!refPtr) return NULL;
}
while (refPtr->next) {
mainPtr = mainPtr->next;
refPtr = refPtr->next;
}
return mainPtr;
}
};