剑指Offer---面试题15:链表中的倒数第k个节点

一.题目


输入一个链表,输出该链表中倒数第k个结点。

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
    //
    }
}    

二.分析:

  1. 由题目给出的ListNode类可知,该链表是一个单链表,具有单向可达性 ,所以“先找到最后一位,然后在回溯到第k位”这一思路是行不通的;
  2. 假设链表长度为n,那么倒数第k项就是顺数第n-k+1项;马上形成第二种思路“首先遍历一遍求得n,在遍历一遍求得n-k+1项”; ok,这思路没问题.但是如果只能遍历一遍的话,那么这个解法就不满足了.
  3. 整两个指针(初始化指向第一个Node),一个指针(rightNode)先走k-1步,然后两指针一同往后走,直至第一个指针走到最后一个Node处,此时第二个指针(leftNode)指向的Node就是倒数第k个Node;

三.进一步分析

上诉思路是很清晰的,但是这个题目需要考察的使我们代码的鲁棒性,而容错性其重要的一个体现;我们思考的需要很缜密,对于题目中给出的方法的参数head,k要进行严格判断.若如下三种情况出现但是没有合理的处理,程序会崩溃:

1. k<=0,此时的k是没有意义的,应为”倒数第k位”,只有当k>0时,才有意义;
2. head=null时,此时链表就不存在,也是没有意义的.
3. k>大于链表结点数时,也是没有意义的.


四.代码

分析完之后,代码就简单了,直接贴:

 public ListNode FindKthToTail(ListNode head,int k) {
        //正常情况下
            ListNode rightNode=null;
            ListNode leftNode=null;
            if(head!=null&&k>0){//处理第1,2中情况
                 rightNode=head;
                 leftNode=head;
            }else{
                 return null;
            }
            for(int i=0;i<k-1;i++){
                if(rightNode.next!=null){ //处理第3种情况
                    rightNode=rightNode.next;
                }else{
                    return null ;
                }
            }
            while(rightNode.next!=null){
                leftNode=leftNode.next;
                rightNode=rightNode.next;
            }
            return leftNode;
}

五.扩展

扩展1:判断一个单链表是否形成环形的结构.

思路:定义两个指针,同时从链表的头结点出发,一个指针一次都两步,一个指针一次走一步;如果走得快的指针追上了走得慢的指针,那么该单链表存在环;如果做得快的指针走到了next=null处,那么该单链表就不存在环;

扩展2:求链表的中间结点;但节点数为奇数时,返回中间结点,当结点数为偶数时,返回中间两个结点的任意一个节点;

思路:整两指针,一个一次走两步,一个一次走一步,当走得快的指针走到末尾时,走得慢的指针就放好指向链表的中间结点;


六.总结

当我们用一个指针不能解决链表问题的时 候,我们可以用两个指针,一个走得快一点,一个走的慢一点,或者可以让一个指针在链表中先走上若干步;同时也要注意代码的鲁棒性,对输入进行严格的检查;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值