输入一个链表,输出该链表中倒数第k个结点。
解法: 定义两个指指针。第一个指针从链表的头指针开始遍历向前走k-1,第二个指针保持不动;
从第k步开始,第二个指针也开始从链表的头指针开始遍历。
由于两个指针的距离保持在k-1,当第一个(走在前面的)指针到达链表的尾节点时,第二个指针(走在后面的)指针正好是倒数第k个节点。
相关题目:
1、求链表的中间节点。如果链表中结点总数为奇数,返回中间结点;如果结点总数是偶数,返回中间两个结点的任意一个。
解法: 定义两个指针,同时从链表的头结点出发,一个指针一次走一步,另一个指针一次走两步。
当走得快的指针走到链表的末尾时,走得慢的指针正好在链表的中间。
2、判断一个单向链表是否形成环。
解法:定义两个指针,同时从链表的头结点出发,一个指针一次走一步,另一个指针走两次。
如果走得快的指针追上走得慢的指针,那么链表就成环;
如果走得快的指针走到了链表的末尾(next指向null)都没有追上第一个指针,则不是环。
代码:
public class Offer15 {
public static class ListNode{
int value;
ListNode next;
ListNode(int val){
this.value = val;
}
}
public ListNode findKthToTail(ListNode head, int k){
if(head == null || k == 0)
return null;
ListNode pAhead = head;
ListNode pBehind = null;
for(int i = 0;i<k-1;i++){
if(pAhead.next != null)
pAhead = pAhead.next;
else
return null;
}
pBehind = head;
while(pAhead.next != null){//第一次我这里写成pAhead != null,结果运行时当k=5时输出2,k=1时报错
pAhead = pAhead.next;
pBehind = pBehind.next;
}
return pBehind;
}
public static void main(String[] args) {
Offer15 ofo15 = new Offer15();
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
//node5.next = null;
// 1功能测试(第k个节点在链表的中间
System.out.println(ofo15.findKthToTail(node1, 3).value);
// 1功能测试(第k个节点是链表的头节点
System.out.println(ofo15.findKthToTail(node1, 1).value);
// 1功能测试(第k个节点是链表的尾节点
System.out.println(ofo15.findKthToTail(node1, 5).value);
//特殊输入测试(链表头节点为NULL指针
System.out.println(ofo15.findKthToTail(null, 5));//这里若是和上面一样有.value,则报错Exception in thread "main" java.lang.NullPointerException
//特殊输入测试(链表的节点总数少于k,在for循环中遍历链表可能会出现指向null的next
System.out.println(ofo15.findKthToTail(node1, 7));
//特殊输入测试(k=0
System.out.println(ofo15.findKthToTail(node1, 0));
}
}
运行结果:
3
5
1
null
null
null