得到链表中倒数k个节点
前言
链表的操作以链表的遍历为基础。倒数k个节点可以通过单指针两次遍历得到,也可以通过双指针一次遍历得到。Java中没有指针,可以当着对象来理解。对象名指向new出来的对象。
一、单指针
第一次遍历得到链表的总节点数,再通过总节点数count和k的比较来确定第二次遍历走多少步。
1、源码
//Definition for singly-linked list.
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
public ListNode getKthFromEnd(ListNode head, int k) {
//第一遍计数count,如果count<=k,就返回head,反之,从头往后遍历count-k处,然后返回指针。
int count = 0;
ListNode point = head;
while(point != null){
count++;
point = point.next;
}
int gap = count - k;
if(gap <= 0)
return head;
count = 0;
point = head;
while(point != null){
point = point.next;
count++;
if(count == gap)
return point;
}
return null;
}
二、双指针之快慢指针
快指针先走k步,结束循环。再通过另一个循环来同时启动慢指针和快指针的前进,直到快指针到达链表的末尾。
//Definition for singly-linked list.
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
//快慢指针
public ListNode getKthFromEnd2(ListNode head, int k) {
//让两个指针一个在开头,一个在第k个地方,同时行走,当第一个指针指向尾巴时,第二个指针就指向了这段的开头。取得最后的k个节点。
if(head == null || k <= 0)
return null;
int count = 1;
ListNode pointF = head,pointS = head;
while(pointF.next != null && count < k){
count++;
pointF = pointF.next;
}
if(pointF == null)
return null;
while(pointF.next != null){
pointF = pointF.next;
pointS = pointS.next;
}
return pointS;
}
总结
快慢指针也遍历了两次,但是第一次并没有遍历到末尾,第二次遍历也不是从开头开始遍历。
快慢指针也优点像一个滑动窗口,一旦拿到滑动窗口,就开始滑动。