[leetCode]剑指 Offer 22. 链表中倒数第k个节点

在这里插入图片描述

解法

  • 第一种思路是从前向后遍历到链表尾,再从尾部回溯k-1次。由于是单链表所以这种方法不能实现
  • 第二种思路是如果已知链表长度为n那么倒数k个节点为n-k+1个节点。链表长度需要遍历一遍链表才能知道,这种解法一共需要遍历两次
  • 有没有只遍历一次的解法呢?这时使用两个指针即可解决问题。
    1. 使用一个指针A指向链表头部,向后移动k-1次。
    2. A指针移动K-1次后,使用指针B指向头节点,此时两个指针之间相差k-1步
    3. 同时移动A、B指针,当A指针到达链表尾部时,B指针所指节点即为倒数第k个节点
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        ListNode pAhead = head;
        ListNode pBhead = null;
        for(int i = 0; i < k-1; i++)
            pAhead = pAhead.next;
        pBhead = head;
        while(pAhead.next != null){
            pBhead = pBhead.next;
            pAhead = pAhead.next;
        }
        return pBhead;
    }
}

鲁棒性

这题需要注意代码的鲁棒性,上述代码还存在如下问题:

  1. 输入的head为空引用时怎么处理
  2. 如果链表长度小于k,在for循环中指针会向前走k-1步,会照成控制异常
  3. 在c/c++中如果,k类型为unsigned int 时,如果k 为 0,在for循环中k-1为4294967295。循环的执行次数远远超出估计
    鲁棒的代码如下:
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        if(head == null || k <= 0) return null;
        ListNode pAhead = head;
        ListNode pBhead = null;
        for(int i = 0; i < k-1; i++){
            if(pAhead.next != null){
                 pAhead = pAhead.next;
            }else {
                return null;
            }
        }
        pBhead = head;
        while(pAhead.next != null){
            pBhead = pBhead.next;
            pAhead = pAhead.next;
        }
        return pBhead;
    }
}
posted @ 2020-08-18 12:02  消灭猕猴桃  阅读(63)  评论(0编辑  收藏  举报