考察点
链表
知识点
双指针遍历链表
题目
分析
这道题目需要倒数第k个结点,假设链表中总共n个结点,倒数第k个结点就是正数第n-k+1个结点,这是个数学小tips,如果不能识别出这层关系的话可以通过归纳法的方式找出数字的规律,这种方法需要我们遍历2遍链表,第一遍算出n的值,第二步找到第n-k+1个结点。有没有只遍历一次链表的方法呢?肯定有,链表的考点一般会考到双指针,所以思维一定要往双指针上靠,通过第一种方法能够看到倒数第k个结点就是正数第n-k+1个结点,最后那个结点是正数第n-1个结点,俩个结点相差n-1-(n-k+1) = k-2个步,按照这个思路,如果我们先让其中一个指针从头结点开始往后走k-2步,然后让第二个指针从头结点开始和第一个指针同时往后遍历,当快指针遍历到最后一个结点的时候,慢指针所指的结点就是我们要寻找的结点
public class LinkNode {
int val;
LinkNode next;
public LinkNode(int data) {
this.val = data;
this.next = null;
}
}
public class LinkList {
LinkNode head;
public LinkList() {
this.head = null;
}
//找到倒数第k个元素
public LinkNode findTailKth(int k) {
if (this.head == null || k <= 0) {
return null;
}
LinkNode pFirst = this.head;
LinkNode pSecond = this.head;
for(int i = 0;i < k - 1;i++) {
if (pFirst.next == null) {
return null;
}
pFirst = pFirst.next;
}
while(pFirst.next != null) {
pSecond = pSecond.next;
pFirst = pFirst.next;
}
return pSecond;
}
//添加元素
public void addNode(int data) {
LinkNode node = new LinkNode(data);
if (this.head == null) {
this.head = node;
} else {
LinkNode cur = this.head;
while(cur.next != null) {
cur = cur.next;
}
cur.next = node;
}
}
//清空
public void clear() {
this.head = null;
}
}
public class Fifteen {
public static void main(String[] args) {
LinkList linkList = new LinkList();
linkList.addNode(1);
linkList.addNode(2);
linkList.addNode(3);
linkList.addNode(4);
LinkNode val = linkList.findTailKth(1);
if (val != null) {
System.out.println("val " + val.val);
}
LinkNode vala = linkList.findTailKth(2);
if (vala != null) {
System.out.println("vala " + vala.val);
}
LinkNode valb = linkList.findTailKth(22);
if (valb != null) {
System.out.println("valb " + valb.val);
}
LinkNode valc = linkList.findTailKth(-22);
if (valc != null) {
System.out.println("valc" + valc.val);
}
linkList.clear();
LinkNode vald = linkList.findTailKth(2);
if (vald != null) {
System.out.println("vald" + vald.val);
}
}
}