题目一:输入一个链表,输出该链表中倒数第k个结点。
方法一:假设整个链表有n个节点,那么倒数第k个节点就是从头节点开始的第n-k+1个节点。第一次遍历统计出链表中节点的个数,第二次就能找到倒数第k个节点。
/**
*
* 得到链表节点个数m
* 注意的是不要使用head统计节点,因为链表指针移动过去了,还得移动回来
*/
public ListNode FindKthToTail(ListNode head,int k) {
if(head==null || k<=0)
{
return null;
}
int count=0;
ListNode h=head;
while(h!=null)
{
count++;
h=h.next;
}
ListNode l=head;
for(int i=0;i<count-k;i++)
{
l=l.next;
}
if(k>count)
{
return null;
}else {
return l;
}
}
方法二:只需要遍历链表一次。第一个指针从链表的头指针开始遍历向前走k-1步,第二个指针保持不动。从第k步开始,第二个指针也开始从链表的头指针开始遍历。由于两个指针的距离保持在k-1,当第一个指针到达尾节点时,第二个指针正好指向倒数第k个节点。
需要考虑下面三种情况:
- 输入的链表节点的总个数小于k,由于第一个指针需要走k-1步,会由于空指针造成程序崩溃
- 输入的参数k为0。由于k是一个无符号整数,在k-1中得到的将不是-1。因此,也会造成程序崩溃。
- 输入的链表节点是个空指针,由于代码会试图访问空指针指向的内存,从而造成程序崩溃。
所以针对这三个问题,要分别进行处理:
public ListNode FindKthToTail1(ListNode head,int k){
if(head==null || k<=0)
{
return null;
}
ListNode l=head;
ListNode r=head;
for(int i=0;i<k-1;i++)
{
if(l.next==null)
{
return null;
}
l=l.next;
}
while(l.next!=null)
{
l=l.next;
r=r.next;
}
return r;
}
相关使用两个指针的题目:求链表的中间节点,如果链表中节点总数是奇数,则返回中间节点;如果节点总数是偶数,则返回中间两个节点中的任意一个。解法:定义两个指针,同时从链表的头结点出发,一个指针走一步,另一个指针一次走两步。当走的快的指针走到链表末尾是,走的慢的指针正好在链表中间。