题目描述
输入一个链表,输出该链表中倒数第k个结点(k从1开始)。
思路1
假设链表中共有n个节点,倒数第k个节点即为正数第n-k+1个节点(正数倒数编号都从1开始)。所以我们首先要将链表遍历一遍获得长度n,然后再移动到第n-k+1个节点即可。对应代码如下:
/*
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==nullptr || k==0)
return nullptr;
int n = 1;
ListNode* temp = pListHead;
while(temp->next!=nullptr){
temp = temp->next;
n++;
}
if(n<k)
return nullptr;
ListNode* node = pListHead;
for(int i=1; i<n-k+1; i++)
node = node->next;
return node;
}
};
思路2
思路1主要的缺点是要先把链表遍历一遍来获取链表的长度。为了解决这个问题,我们可以设置两个指针p1和p2, p1和p2的初始值均为链表头head。首先将p1移动k-1步,此时p1还剩n-k+1步到达链表尾。从第k步开始,p2也开始移动,这样等p1到达链表尾时,p2位于链表第n-k+1个节点,也就是链表倒数第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) {
if(pListHead==nullptr || k==0) //unsigned int 0-1!=-1,会造成程序崩溃
return nullptr;
ListNode* p1 = pListHead;
ListNode* p2 = pListHead;
for(unsigned int i=0; i<k-1; i++){
if(p1->next==nullptr) // k大于链表长度
return nullptr;
p1 = p1->next;
}
while(p1->next!=nullptr){
p1 = p1->next;
p2 = p2->next;
}
return p2;
}
};
注意点
1、链表头pListHead为空;
2、链表节点总数小于k;
3、k是无符号整数,当k=0时,k-1=4294967295,会造成不正确的结果或者程序崩溃。
总结
当链表问题用一个指针不好解决时,可以尝试使用两个指针,让其中一个指针走得快,另一个走得慢。