返回

揭秘链表算法中的经典难题,轻松驾驭倒数第k个节点查找!

IOS

在计算机科学的算法领域,链表是一种常见的线性数据结构。链表算法的经典题之一便是查找链表中的倒数第k个节点,看似简单却暗藏玄机。本文将深入解析链表的概念、倒数第k个节点查找的思路和实现,并提供详细的代码示例,帮助你轻松驾驭链表算法的这一难题。

链表的定义与分类

链表是一种由一系列节点组成的线性数据结构,每个节点包含一个数据域和一个指向下一个节点的指针。根据链表中是否存在环形结构,链表可以分为有环链表和无环链表。

倒数第k个节点查找的思路

查找链表中的倒数第k个节点,核心思想是利用两个指针同时遍历链表。第一个指针从链表头部开始遍历,先前进k步;第二个指针紧随其后。当第一个指针遍历到链表尾部时,第二个指针指向的节点即为倒数第k个节点。

实现步骤

1. 创建链表

首先,我们需要创建两个链表:一个无环链表和一个有环链表。

2. 倒数第k个节点查找算法

// 无环链表
public static Node findKthFromEnd_noCycle(Node head, int k) {
    if (head == null || k <= 0) {
        return null;
    }

    Node fast = head;
    Node slow = head;

    // 快指针先前进k步
    while (k > 0) {
        fast = fast.next;
        k--;
    }

    // 快指针到达链表尾部时,慢指针指向倒数第k个节点
    while (fast != null) {
        fast = fast.next;
        slow = slow.next;
    }

    return slow;
}

// 有环链表
public static Node findKthFromEnd_cycle(Node head, int k) {
    if (head == null || k <= 0) {
        return null;
    }

    // 计算链表的长度
    int len = 0;
    Node cur = head;
    while (cur != null) {
        len++;
        cur = cur.next;
    }

    // 将k转化为正值
    k = len - k;

    // 重新遍历链表
    cur = head;
    while (k > 0) {
        cur = cur.next;
        k--;
    }

    return cur;
}

关键细节

  • 无环链表的查找过程简单直接,利用两个指针同步遍历链表即可。
  • 有环链表的查找需要先计算链表的长度,然后将k转化为正值,再重新遍历链表找到倒数第k个节点。

代码示例

// 无环链表
Node head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
head.next.next.next = new Node(4);
head.next.next.next.next = new Node(5);

System.out.println(findKthFromEnd_noCycle(head, 2).val); // 输出:4

// 有环链表
Node head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
head.next.next.next = head; // 形成环

System.out.println(findKthFromEnd_cycle(head, 2).val); // 输出:3

总结

通过本文的详细讲解,你已经掌握了链表算法经典难题——倒数第k个节点查找的思路和实现。无论是无环链表还是有环链表,都可以使用两个指针的同步遍历或计算链表长度的方法高效解决。只要熟练掌握这些技巧,你将能够轻松应对链表算法中的各种挑战。