welcome to my blog
剑指offer面试题22(java版):链表中倒数第K个节点
题目描述
输入一个链表,输出该链表中倒数第k个结点。
笔记
- 要进行健壮性判断: 输入的节点为null; k<=0都是异常情况
复杂度
- 时间复杂度: O(n)
- 空间复杂度: O(1)
第二次做
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
//倒数第零个节点,没有定义
if(head==null || k==0) return null;
/*
如果链表长度达不到k该怎么检查出来?
只能一个一个遍历,如果遍历的个数没有到k就遇到null了,则返回null
所以判断条件是:遍历的个数与链表是否结尾
*/
/*
创建两个指针,fast和slow相隔k-1个节点,这样fast到达最后一个节点的话,
slow位于倒数第k个节点
注意:不要让fast到达null,这样的话fast和slow得相隔k个节点,
由于slow和fast的起点是head,所以相隔k个节点的话需要链表中有k+1个节点
这样判断的话就麻烦了,比如链表只有k个节点,检查长度时fast走到了null,
此时不能返回null,需要配合k进行判断,就变麻烦了。
所以一步到位,让fast和slow相隔k-1个节点,不满足就说明链表长度小于k,返回null
*/
ListNode slow = head, fast = head;
//先让fast往前走k-1步,确保链表中有k个节点
//本题要牢记的细节:先移动再判断(逻辑问题;脑中过一遍)
for(int i=0; i<k-1; i++){
fast = fast.next;
if(fast == null)
return null;
}
//slow,fast一起走,直到fast走到最后一个节点
while(fast.next != null){
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
// input check
if(head == null || k<=0)
return null;
//execute
ListNode fast = head;
ListNode slow = head;
// 下面这个循环让fast位于第K个Node上; 非正常退出循环说明链表长度不足K
for(int i = 0; i < k - 1; i++){ // 包括slow在内, 从slow到fast是K个节点; 所以fast得先向前移动K-1步
if(fast.next == null)
return null; // 链表长度不足K
fast = fast.next;
}
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
极其简洁的代码
先掌握上面那种方法, 感觉一般面试时主要是思维缜密性的体现
public ListNode FindKthToTail(ListNode head,int k) {
ListNode p, q;
p = q = head;
int i = 0;
for (; p != null; i++) {
if (i >= k)
q = q.next;
p = p.next;
}
return i < k ? null : q;
}