题目描述
输入一个链表,输出该链表中倒数第k个结点
分析:方法一:遍历两次链表,第一个统计出链表的节点的个数(例如n个),第二次就遍历到第n-k个节点,就是倒数第k个节点。这种方法要遍历两次链表。
方法二:定义两个指针,第一个指针从链表头开始先走k-1步,然后两个指针同时向前走,当走的快的指针到达链表末尾最后一个节点时,慢的指针指向倒数第k个节点。
方法二的代码实现:
public class Solution{
public ListNode FindKthToTail(ListNode head,int k){
if(head==null||k<=0)
return null;
ListNode p = head;
int i = 1;
while(i<k&&p!=null){
p = p.next;
i++;
}
if(p==null) //如果k大于链表节点的个数
return null;
ListNode q = head;
while(p.next!=null){ //p和q之间举例了k-1个节点
q = q.next;
p = p.next;
}
return q;
}
}
说明:这个题目的考点除了想到使用两个指针来一次遍历链表找到倒数第k个节点外,还要注意特殊用例:
1)输入的头指针为空指针,此时直接返回
2)输入的k为0,此时返回null
3)如果k大于链表的个数,此时返回null
ListNode p = head;
int i = 1;
while(i<k&&p!=null){
p = p.next;
i++;
}
if(p==null) //如果k大于链表节点的个数
return null;
如果k大于链表的个数,此时p=null会退出while循环,这时通过if(p==null)判断后输出为空。
类比:在链表的插入时,例如在第i个节点插入时,我们也要先定位到第i-1个节点,这里也有刚刚所说的几个条件的判断,例如链表中有四个元素,我们想在第6个元素前插入,此时也要进行相应的处理。
//在第i个节点前插入节点
/*
注意一:此时定位到第i-1个节点
注意二:现在没有头结点的情况,所以在第一个节点前插入有点特殊
*/
public void ListInsert(int i,Item item){//在第i个节点前插入节点
Node<Item> p = head;
int k = 2;
while(k<i&&p!=null){ //定位到i-1个节点
p = p.next;
k++;
}
if(p==null&&i!=1) //如果i>k+1此时,直接返回null
return;
Node<Item> q = new Node<>(item);
if(i==1){ //插入在第一节点前插入操作有点特殊
q.next = head;
head = q;
}
else{
q.next= p.next;
p.next = q;
}
}