题目描述:
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。
示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
要找到倒数第k个节点,首先先到的想法就是先确定链表的长度n,再重头开始前进n-k+1步。但是确定长度n要先遍历一次链表,到后面找到倒数第k个节点,还要遍历一次链表,这就需要遍历两次了。
有一个想法:倒数第k个节点距离尾节点的距离就是k-1,设置两个指针,一个前指针,一个后指针,前指针先往前走,走了k-1步之后,前后指针就同时往前走,直到前指针到达尾部,这样后指针就在前面距离尾部k-1的位置了,返回后指针的节点就可以了。
这个中间还要防止输入节点为空,或者倒数第0个节点的情况,这两种情况下都是无意义的,返回null;再有就是输入的k,比链表的长度n还大,所以是找不到这个节点的,处理这个情况需要再遍历的时候加入一个判断条件,如果还没到达k,就已经到了链表的尾部,就直接返回null。
代码(Java):
public class doingmyself {
public static void main(String[] args) {
int[] nums = {1,2,3,4,5};
List<ListNode> list = new ArrayList<ListNode>();
for(int num:nums) {
ListNode node = new ListNode(num);
list.add(node);
}
for(int i = 0;i<list.size()-1;i++) {
list.get(i).next = list.get(i+1);
}
ListNode head = list.get(0);
ListNode ans = getKthFromEnd(head,2);
System.out.println();
}
public static ListNode getKthFromEnd(ListNode head, int k) {
if(head == null || k == 0) { //如果输入的节点是空的,或者k等于零,倒数第0个没意义,直接返回null
return null;
}
//设置前后两个节点,利用倒数第k个节点与尾节点有k-1的距离,采用一次遍历找出倒数第k个节点
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pFront = dummy; //两个指针都从head节点的前节点开始出发
ListNode pBehind = dummy;
for(int i = 0;i<k-1;i++) { //尾节点和倒数第k个节点有k-1的距离,先让前节点前进k-1的距离
if(pFront.next != null) { //条件判断,预防k比输入节点的长度还大,这种情况下直接返回null
pFront = pFront.next;
}else {
return null;
}
}
while(pFront.next != null) { //前节点前进了k-1之后,前后节点一起向前出发,直到前节点到达了最后一个节点,后节点就到达了倒数第k个节点
if(pFront.next != null) { //条件判断,预防k比输入节点的长度还大,这种情况下直接返回null
pFront = pFront.next;
pBehind = pBehind.next;
}else {
return null;
}
}
return pBehind; //返回找到的倒数第k个节点
}
}
class ListNode{
int val;
ListNode next;
ListNode(int x){
val = x;
}
}