题目描述
输入一个链表,输出该链表中倒数第k个结点。
方法一:普通解法
很显然,求倒数第k个,可以转换成求正数第多少个呢?
看个例子:
假设有5个节点,序号1表示第1个节点,假设求倒数第K个,那么正数就应该是从头结点开始往后推(n-k)个,n自然代表所有节点的个数(不包含空节点),也可以说n代表指针的个数,为啥这么说呢?因为一个节点后面跟着一个指向下一节点的指针。
这里n=5,所以需要从头结点往后经过n-K = 3个指针。
有了上面的过程,还需要考虑2个细节
- k<=0 或者头结点最开始就为空,也就是没有节点
- 节点的总个数 < K
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if (!pListHead || k <= 0)
return nullptr;
int n = 0;
ListNode *cur = pListHead;
while (cur) {
cur = cur->next;
++n;
}
if (n < k)
return nullptr;
n -= k;
while (n--) {
pListHead = pListHead->next;
}
return pListHead;
}
};
时间复杂度:O(2*n),n为链表的总长度,如果k总是在倒数第一个节点,那么此方法需要遍历链表2次
空间复杂度:O(1)
方法二:严格的O(n)解法,快慢指针
首先让快指针先行k步,然后让快慢指针每次同行一步,直到快指针指向空节点,慢指针就是倒数第K个节点。
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(k <= 0|| !pListHead)
return nullptr;
ListNode* fast = pListHead;
ListNode* slow = pListHead;
while(k){
if(fast)
fast = fast->next;
else
return nullptr;
k -= 1;
}
while(fast){
slow = slow->next;
fast = fast->next;
}
return slow;
}
};