没有输出的输入是不完整的

0%

剑指offer-链表中倒数第K个节点

本文为剑指 offer 系列第十六篇。
主要知识点为链表,就是在链表遍历的基础上进行查找操作,细心一点也没啥问题。

题目描述

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

解题思路

思路1

先将链表遍历一遍,计算总的结点的个数。
然后计算倒数第k个是正数第多少个,然后再遍历一遍,找到要输出的结点。

思路2

通过双指针来解决问题。快的结点要比慢的结点提前k个,
当后面那个走到尾节点所指向的空结点的时候,慢的指针刚好指向要求输出的节点。

解题代码

思路1代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* phead, unsigned int k) {
//方法一,先跑一遍,计算总的个数。然后计算倒数第k个是正数第多少个,然后再遍历一遍。
if(!phead || k == 0) return NULL;
int count = 0;
ListNode* p = phead;
while(p){
p = p->next;
count++;
}
if(count < k) return NULL;
p = phead;
for(int i = count-k; i>0; i--){
p = p->next;
}
return p;
}
};

时间复杂度为O(n),空间复杂度为O(n)

思路2代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
ListNode* FindKthToTail(ListNode* phead, unsigned int k) {
//方法二:快慢双指针。
if(!phead || k == 0) return NULL;
ListNode* fast, *slow;
fast = slow = phead;
for(int i = 0;i<k;i++){
fast = fast->next;
if(!fast && i==k-1) return phead;
if(!fast) return NULL;
}
while(fast){
fast = fast->next;
slow = slow->next;
}
return slow;
}
};

或者可以用另一种写法,比较优美一点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(!pListHead || k <= 0) return NULL;
ListNode* fast = pListHead;
ListNode* slow = pListHead;
while(k>0 && fast){
k--;
fast = fast->next;
}
while(fast){
fast = fast->next;
slow = slow->next;
}
return k>0?NULL:slow;
}
};

时间复杂度为O(n),空间复杂度为O(n)
以上,本题结束!