题目来源:牛客网-剑指Offer专题
题目地址:链表中倒数第k个结点
题目描述
输入一个链表,输出该链表中倒数第k个结点。
节点结构如下:
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
题目解析
这是一道和链表相关的题,对于这种题目,在熟悉链表的基本操作解决基本问题之余,也一定要记得处理空指针之类的有可能造成程序异常终止的情况,不要贪图方便(尤其是那些前竞赛选手 )。
方法一:
这是一种最常规的方法,先遍历一次链表求出链表的的长度
,然后将倒数第 k 个节点转换为顺数第len-k
个节点,最后第二次遍历去求解即可。
public class Solution {
public ListNode FindKthToTail(ListNode head, int k) {
if (head == null || k < 1)
return null;
int len = 0, i = 0;
//计算链表长度
ListNode p = head;
while (p != null) {
p = p.next;
len++;
}
//如果k比len还大,就直接返回null
if (k > len) {
return null;
}
//找倒数第k个节点(其实就是顺数第len-k个节点)
p = head;
while (i < len - k) {
p = p.next;
i++;
}
return p;
}
}
方法二:
其实我们只需要进行一次遍历操作就可以求出需要的答案,网上很多人把这个称之为“快慢指针法”,即让慢指针在快指针移动
个节点后再开始移动,当快指针移动到链表末尾(null)时,慢指针就到达了倒数
个节点。
听起来有点玄乎?请听我细细道来~
如下图所示,由于我们最后到达的是末端(null),那我们就从末端开始移动
个节点,就到达了我们的倒数第
个节点,也就是我们的目标
。最后再从
移动到慢指针
的位置。
现在,我们把部分过程逆转过来,我们要从
移动到慢指针
的位置。问题是我们又不知道要移动多少个节点,暂时设为
,于是有
我们让快指针先移动了
个节点,再让慢指针和快指针一起移动,实际上就是用快指针去度量链表的长度
,将慢指针移动的距离限定为
个节点。
public class Solution {
public ListNode FindKthToTail(ListNode head, int k) {
if (head == null || k < 1)
return null;
ListNode p, q;
p = q = head;
int i = 0;
for (; p != null; i++) {
if (i >= k) {
//快指针移动了k个节点后,慢指针开始移动
q = q.next;
}
//快指针需要一直移动
p = p.next;
}
return i < k ? null : q;
}
}
本文为原创,作者博客地址为:Veggie的博客
如果本文对你有所帮助,要记得点赞哦~