本题来自:剑指 Offer 22. 链表中倒数第k个节点
1.问题描述:
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 2 个节点是值为 4 的节点。
示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
2.题解:
2.1.遍历链表法解题思路:
遍历一遍链表,可以得到链表的长度,然后用链表的长度length-k+1=倒数第k个结点所在的位置
注意,有关链表的题目最好设置一个头结点,头结点不带任何数据,即哨兵结点,这样方便运算的实现,也便于后期再找到整个链表,头结点是不能改的,这是一个习惯。
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
if(head==null){
return null; //如果链表头为空,返回空
}
ListNode realHead=new ListNode(-1); //创建头结点
realHead.next=head; //让创建的头结点指向题中所给的链表头
ListNode p=realHead.next;
int length=0;
//计算链表的长度
while(p!=null){
length++;
p=p.next;
}
//计算倒数第k个结点的位置
int index=length-k+1;
if(index<0){
return null; //此时k非法
}
p=realHead; //p再次遍历
System.out.println(index);
for(int i=0;i<index;i++){
p=p.next;
}
return p;
}
}
2.2.双指针法解题思路:
使用双指针则可以不用统计链表长度。
构造哨兵头结点以及双指针:构造哨兵头结点,以及前指针q和后指针p 。
构建双指针距离: 前指针 q先向前走 k 步(结束后,双指针p 和 q间相距 k 步)。
双指针共同移动: 循环中,双指针 p和 q每轮都向前走一步,直至 q走过链表 尾节点 时跳出(跳出后, p与尾节点距离为 k-1,即 p指向倒数第 k 个节点)。
返回值: 返回 p即可。
class Solution {
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode realHead=new ListNode(-1); //构造头结点
realHead.next=head;
ListNode p=realHead; //后指针
ListNode q=realHead; //前指针
for(int i=0;i<k;i++){ //前指针后移k位
if(q==null){
return null;
}
q=q.next;
}
while(q!=null){ //前指针和后指针同时后移
p=p.next;
q=q.next;
}
return p; //返回后指针即可
}
}