题目描述
输入一个链表,输出该链表中倒数第k个结点。
题目分析
题目提供的是单向链表,仅有next指针,即仅可从头到尾访问。该问题主要集中在两个点:
- 判断k的值是否大于链表的长度;
- 如何找到倒数第k个结点:
- 利用栈的“先进后出”的特点,作k-1次出栈操作,返回栈顶元素;
- 设链表长度为n,倒数第k个结点就是第(n-k+1)个结点,可以用数组或者快慢指针法实现。
解题
利用栈
利用C++STL中的stack解决该问题,主要思路如下:
- 遍历链表,并让链表结点入栈;
- 判断stack的长度与k的大小关系;
- 出栈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) {
stack<ListNode*> s;
while(pListHead != NULL){
s.push(pListHead);
pListHead = pListHead->next;
}
if(s.size()<k || k <= 0)
return NULL;
while(k > 1){
s.pop();
k--;
}
return s.top();
}
};
双指针:快慢指针
利用双指针法定位到第(n-k+1)个结点,主要思路如下:
- 定义两个指针均赋值头结点;
- 其中一个指针先走k步,定义为快指针,另一个为慢指针;
- 判断此时快指针是否为NULL,否是,则k大于链表长度;
- 否则,快慢指针同时往下走,当快指针为NULL时,即尾结点下一个位置时,慢指针指向的即为第(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) {
ListNode* pFast = pListHead;
ListNode* pSlow = pListHead;
if(k == 0)
return NULL;
for(int i = 0; i < k; i++){
if(pFast == NULL)
return NULL;
pFast = pFast->next;
}
while(pFast != NULL){
pFast = pFast->next;
pSlow = pSlow->next;
}
return pSlow;
}
};
暴力解法
定义结点数组,因为数组元素从下标0开始存储,所以数组[n-k]即为第(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) {
ListNode* node[10010];
int length = 0;
while(pListHead != NULL){
node[length++] = pListHead;
pListHead = pListHead->next;
}
return k > length ? NULL : node[length-k];
}
};
以上思路为个人想法和网络各位大佬的题解的结合,欢迎讨论与指正。