世界这么大,人生这么长,总会有这么一个人,让你想要温柔对待。
原题如下:
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。
审题:
题目也还是很好理解,就是输出一个单链表的倒数第K个结点。
可能给我们的单链表的情况:
1.空的单链表;
2.有多个结点,但是K的值不合理(即K的值大于链表的长度或K小于1);
3.有多个结点,且K的值是合理的。
方案设计:
本题的核心问题是如何确定K的值
第一种方案:
这种方案肯定是大家都能想到的,就是先通过遍历一遍链表,计算出单链表有几个结点。则可以判断K值是否合理,也就可以得出其倒数第K个结点是哪一个结点了。这种方案易懂,编写算法也容易,但是这种方案相比执行效率不高,毕竟要通过遍历两次。在这里就不分析过程了,直接给出代码如下:
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
if(k<1||head==NULL)return NULL;
int num=0;
ListNode*traversal=head;
while(traversal)//计算链表有几个结点
{
num++;
traversal=traversal->next;
}
traversal=head;//重新指向头结点
if(k>num)return NULL;//判读K值是否合理
for(int i=0;i<num-k;i++)
{
traversal=traversal->next;
}
return traversal;
}
};
第二种方案:
第二种方案,根据其给的K值出发,利用快慢双指针让快指针先走K个结点。如果快指针还没有走完这K次就指向了NULL,则认为K是不合理的。否则再让两个指针一起走,当快指针为NULL时,慢指针所指的结点就是倒数第K个结点。假如有如下的单链表:k=2;
让快指针和慢指针都初始为指向第一个结点,如下:
让快指针先走K个结点,即两个结点,如下:
再让快慢指针一起走,当快指针指向NULL时,慢指针所指的结点就是倒数第K个结点,如下:
这种方案的基本原理在于两个指针始终保持K个结点的距离。
代码实现如下:
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
if(k<1||head==NULL)return NULL;
ListNode*fast=head;
ListNode*slow=head;
for(int i=0;i<k;i++)//让快指针提前走K个结点
{
fast=fast->next;
}
while(fast)//再让快慢指针一起走
{
fast=fast->next;
slow=slow->next;
}
return slow;
}
};
这种方案只需要遍历一次单链表就可以了。
学会了嘛,我是老胡,感谢阅读!!❤️ ❤️