该题思路上最容易想到的应该是顺序查找了,这也是我的第一思路
我们只需要先遍历链表,计算结点数量,最后遍历链表,遇到第n-k+1个结点时break,最后return即可(这里n代表链表结点总数)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
//直接迭代
ListNode* getKthFromEnd(ListNode* head, int k) {
int cn1=0,cn2=0;
ListNode* p=head;
while(p!=NULL)
{
cn1++;//计算结点总数
p=p->next;
}
p=head;
while(p!=NULL)
{
cn2++;
if(cn2==(cn1-k+1))//遇到
{
break;
}
p=p->next;
}
return p;
}
};
2.数组转化
实际上这种方法与上面的顺序查找的方法大同小异
我们直接将每一个链表结点都放到数组中,最后直接输出下标为 数组大小-k 的那一个结点即可(这里没有加1是因为数组下标从0开始)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
vector<ListNode*>v;
ListNode* p=head;
int i=0;
while(p!=NULL)
{
v.push_back(p);//把每个结点放到数组中
p=p->next;
}
return v[v.size()-k];
}
};
3.快慢指针(没错,又是快慢指针)
该方法来解决该题也是所有方法里面效率最高的
我们将第一个指针fast 指向链表的第 k + 1个节点,第二个指针 slow 指向链表的第一个节点,此时指针 fast 与 slow 二者之间刚好间隔 k 个节点。此时两个指针同步向后走,当第一个指针 fast 走到链表的尾部空节点时,则此时 slow 指针刚好指向链表的倒数第k个节点。
我们首先将 fast 指向链表的头节点,然后向后走 k 步,则此时 fast 指针刚好指向链表的
第 k + 1 个节点。
我们首先将 slow 指向链表的头节点,同时slow 与fast 同步向后走,当 fast 指针指向链表的尾部空节点时,则此时返回 slow 所指向的节点即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
ListNode* fast=head;
ListNode* slow=head;
while(k--)
{
fast=fast->next;//快指针先走k步
}
while(fast!=NULL)
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
};