假设链表有n个节点,那么倒数第k个节点,就是从头结点开始数到n-k+1个节点;所以自然就会两种思路:
1、如果可以遍历链表两次的话,第一次计数得到链表节点个数,第二次直接循环找到第n-k+1个节点返回就是。
2、如果链表只允许遍历一次的话,就必须使用两个指针(or引用):第一个指针从头开始走k-1步,第二个指针从头开始走,第一个到链表尾部,第二个指针的所指的就是倒数第k个节点
注意程序的(Robust)鲁棒性(这里鲁棒性是指:程序检查输入是否合乎规范,对于不合理的输入进行合理的处理)
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
//方法一
import java.util.*;
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(k<=0||head==null) return null;
Stack<ListNode> stack = new Stack<ListNode>();// 建立栈结构
while(head!=null){//入栈操作
stack.push(head);
head = head.next;
}
if(k>stack.size()) return null;
ListNode count = head;
for(int i=1;i<=k;i++){//出栈操作
count = stack.pop();
}
return count;
}
}
//方法二:
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(head ==null||k<=0) return null;
ListNode h1 = head;
ListNode h2 = head;
for(int i=1;i<k;i++){//i应该指向第k个时,因为最后一次i 也+1了,但是不满足条件跳出循环了,第一次循环结束,h1指向了第二个,第k-1此循环结束,h1指向第k个
if (h1==null)return null;
h1 = h1.next;
}
//由于循环条件判断的是h1,不是h1.next,循环到第k-1次结束时,h1指向第k个(如果第k个节点不存在的话只能循环到第k-2次,指向第k-1个节点)所以最后h1指向第k个节点是否存在需要如下验证
if(h1==null)return null;//最后一次不满足条件跳出循环了,所以需要验证h1循环的最后一次是否为空;
while(h1.next!=null){//h1到最后一个节点,h2就是倒数第k个节点
h1 = h1.next;
h2 = h2.next;
}
return h2;
}
}
//方法三(跟上面的方法二几乎完全一样,除了循环条件之外)
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(head==null||k<=0)return null;
ListNode p = head,q = head;
for(int i=1;i<k;i++){
if(p.next!=null) p = p.next;//如果p节点后面还有节点,p指向后续节点
else return null; //否则的话,说明节点数少于k个,返回空
}
if(p.next==null)return q;//如果此时k恰好是最后一个节点返回头结点
while(p.next!=null){//如果k不是最后一个节点,循环,判断p是否有后续节点
p = p.next;
q = q.next;
}
return q;
}
}