1.题目
有一个单向非循环链表,找出链表倒数第K个节点。【要求】只遍历一遍链表。
2.思路
我们根据快慢指针的思想,同时发现第一个节点和第3个节点总是差了2步。
根据这个特性,我们先让快指针走两走,让后快慢指针同时走1步,当快指针到达末尾的时候,慢指针就到达倒数第三个节点。
![](https://i-blog.csdnimg.cn/blog_migrate/1a42bf419765b8d9360c8ef37a728198.png)
3.代码
/**
* Describe:
* User:lenovo
* Date:2023-01-05
* Time:22:57
*/
class Node {
int val;
Node next;
public Node() {
}
public Node(int val) {
this.val = val;
}
}
class MyLinkedList {
public Node head;
public MyLinkedList(Node head) {
this.head = head;
}
public MyLinkedList() {
}
}
public class Test {
public static Node findKToTheLast(MyLinkedList list, int k){
//链表为空
if(list.head == null) {
return null;
}
//判断K是否小于=0
if(k <= 0) {
System.out.println("请检查K的合法性");//这里我们可以直接抛出异常
return null;
}
//
Node fast = list.head;
Node slow = list.head;
int count = 0;//这里记录快指针先走了多少步
while(fast.next != null) {
if(count + 1 != k) {
count++;
//fast = fast.next;
}else {
//fast = fast.next;
slow = slow.next;
}
fast = fast.next;
}
//判断快指针是否走完
if(count + 1 == k) {
return slow;
}else {
System.out.println("请检查K的合法性");
return null;
}
}
public static void main(String[] args) {
Node n1 = new Node(1);
Node n2 = new Node(2);
Node n3 = new Node(3);
Node n4 = new Node(4);
Node n5 = new Node(5);
Node n6 = new Node(1);
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = n6;
MyLinkedList myLinkedList = new MyLinkedList(n1);
Node node = findKToTheLast(myLinkedList,3);
System.out.println(node.val);
}
}
判断链表是否为空,为空,返回null,或者抛出异常;
判断k是否小于等于0,小于等于0,返回null或者抛出异常;
我们创建一个变量count记录快指针走的步数,当count+1=k时,我们停止;让后让快、慢指针同时走一步,直到快指针走到最后;
判断上个循环是找到了倒数第k个元素还是不满足条件跳出循环(说明K大于了节点的个数),然后返回相应的节点。
4.总结
本题的重点在于快慢指针的应用,难点在于让快指针先走K-1步思想