剑指Offer题目15:链表中倒数第k个结点(Java)

面试题15:输入一个链表,输出该链表中倒数第k个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是一、二、三、四、五、6。这个链表的倒数第3个结点是值为4的结点。面试

Basic

头指针和中间指针向前遍历法(自创词汇方便记忆)

设置头指针和中间指针,保持相同间隔,朝着同一个方向向前遍历链表。bash

思路分析

须要注意 k <= 0 的场景和k大于链表长度的场景。oop

代码实现

public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if(k <= 0 || head == null) {
            return null;
        }
        ListNode front = head;
        ListNode back = head;
        for(int i=0; i< k-1; i++) {
            //这里须要经过在纸上画出临界点的场景,好比只有5个节点,求倒数第5个节点和倒数第6个节点的场景
            //倒数第5个:k-1 = 4, i 从0~3,总共循环4次,最终遍历到头结点的后序4个节点,即尾节点
            //倒数第6个:k-1 = 5, i 从0~4,总共循环5次,最终遍历到出界,若是出现back.next == null,说明出界了
            if(back.next == null){
                return null;
            }
            back = back.next;
        }
        while(back.next != null){
            front = front.next;
            back = back.next;
        }
        return front;
        
    }
}
复制代码

扩展

题目1:求链表的中间节点

若是链表中的总数为奇数,返回中间节点;若是为偶数,返回中间两个节点的任意一个。ui

思路分析

定义两个指针,同时从链表头结点出发,一个指针一次走一步,另外一个指针一次走两步。spa

当走得快的指针走到链表末尾时,走得慢的指针正好在链表中间。3d

能够在纸上模拟。指针

代码实现

public static Node findMiddleNode(Node head) {
    if (head == null) {
        return null;
    }
    if (head.next == null) {
        return head;
    }
    Node slow = head;
    Node fast = head;
    //一、当链表有偶数个节点时,能够遍历到倒数第 2 个节点,因为能够返回中间两个节点的任意一个,
    // 此时慢指针恰好就是其中两个中间节点的前一个节点,此时定位结束。
    //二、当链表有奇数个节点时,能够遍历到最后一个节点,此时慢指针恰好到正中间的节点,定位结束
    while (fast.next != null && fast.next.next != null) { 
        slow = slow.next;
        fast = fast.next.next;
    }
    return  slow;
}
复制代码

题目2:判断一个单向链表是否造成了环结构。

思路分析

定义两个指针,同时从链表头结点出发,一个指针一次走一步,另外一个指针一次走两步。code

若是走得快的指针追上了走得慢的指针,那么链表就存在环形结。cdn

若是走得快的指针走到了链表末尾,即 next 为 null,则代表链表不存在环形结构。blog

能够在纸上模拟。

代码实现

public static boolean isLoop(Node head) {
    if (head == null || head.next == null) {
        return false;
    }
    Node oneStepNode = head;
    Node twoStepNode = head;
    while (twoStepNode.next != null && twoStepNode.next.next != null) {
        oneStepNode = oneStepNode.next;
        twoStepNode = twoStepNode.next.next;
        //注意避免死循环
        if (oneStepNode == twoStepNode) {
            return true;
        }
    }
    return false;
}
复制代码

相关文章
相关标签/搜索