题目描述:
查找链表的中间节点及倒数第K个节点
解题思路
1.使用快慢指针
public class Arch_02 {
public static void main(String[] args) {
Node head=LinkedListUtils.construct(5);
LinkedListUtils.show(head);
Node mid=getMidNode(head);
System.out.println("链表中间元素:"+mid.value);
int k=2;
Node kNode=getKNode(2, head);
System.out.println("链表倒数第"+k+"个元素:"+kNode.value);
}
public static Node getMidNode(Node head){
//若链表节点数为n,则返回第(n+1)/2个节点
Node slow=head;//慢指针,一次走一步
Node fast=head;//快指针,一次走两步,结尾使若只有一个next则只走一步
while(fast.next!=null){
slow=slow.next;
if(fast.next.next!=null){
fast=fast.next.next;
}else{
fast=fast.next;
}
}
return slow;
}
public static Node getKNode(int k,Node head){
//返回链表倒数第k个节点
Node slow=head.next;
Node fast=head.next;
//快指针先向前走k-1步
int i=0;
for(i=0;i<k-1;i++){
if(fast.next!=null){
fast=fast.next;
}else{
//若链表长度不足,则返回null
return null;
}
}
//快慢指针同时向前遍历,直至快指针将链表遍历结束
while(fast.next!=null){
fast=fast.next;
slow=slow.next;
}
return slow;
}
}
public class LinkedListUtils {
/*
* 构造一个长度为length的链表,返回头结点HEAD
*/
public static Node construct(int length){
Node head=new Node();
Node temp=null;
Node cur=head;
//构造一个链表
for(int i=0;i<length;i++){
temp=new Node();
temp.value=i+1;
cur.next=temp;
cur=temp;
}
return head;
}
/*
* 传入HEAD遍历链表
*/
public static void show(Node head){
StringBuilder sb=new StringBuilder();
sb.append("HEAD");
Node cur=head;
while(cur.next!=null){
sb.append("->"+cur.next.value);
cur=cur.next;
}
System.out.println(sb.toString());
}
/*
* 构造一个长度为length的链表,返回头结点HEAD,节点的值为随机值
*/
public static Node constructRand(int length){
Node head=new Node();
Node temp=null;
Node cur=head;
Random rand=new Random();
//构造一个链表
for(int i=0;i<length;i++){
temp=new Node();
temp.value=rand.nextInt(10);
cur.next=temp;
cur=temp;
}
return head;
}
}
public class Node {
int value;
Node next;
}
分析:
1.鉴于链表的遍历特点,寻找特定位置的节点,使用快慢指针的思想个人觉得是一个不错的思路。快指针和慢指针的使用可以根据具体的业务场景进行设置。
2.当然还有一种方法,依据空间换时间的思想,遍历链表,将节点依次装入一个ArrayList,然后将ArrayList看成一个数组进行操作。个人不推荐,这是一个比较野蛮的方法。