跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

数据结构实战:链表经典面试题解析

链表分割需保持原序,利用双尾插法构建两条子链表;回文结构通过快慢指针找中点并反转后半段比对;相交链表计算长度差对齐起点;环形链表使用快慢指针检测环的存在。核心在于边界条件处理与指针操作细节。

奶糖兔发布于 2026/2/18更新于 2026/6/1116 浏览
数据结构实战:链表经典面试题解析

链表中的经典面试题

链表操作是面试中的高频考点,尤其是涉及指针移动、环检测和结构变换的问题。今天我们来深入探讨几个典型场景,重点在于边界条件的处理和代码的健壮性。

1. 链表分割

题目要求:不能改变原数据顺序,将小于 x 的节点放在前面,大于等于 x 的放在后面。

思路分析: 我们可以维护两条新链表,一条存放小于 x 的节点(bs/be),另一条存放大于等于 x 的节点(as/ae)。遍历原链表时,根据 val 值尾插到对应链表中。最后将两条链表连接起来。

这里有个细节要注意:当第一条链表为空时,直接返回第二条链表;连接完成后,务必将新链表的尾部置为 null,否则可能形成死循环。

class ListNode {
    int val;
    ListNode next = null;
    public ListNode(int val) { this.val = val; }
}

public class Partition {
    public ListNode partition(ListNode pHead, int x) {
        ListNode bs = null, be = null;
        ListNode as = null, ae = null;
        ListNode cur = pHead;
        
        while (cur != null) {
            if (cur.val < x) {
                if (bs == null) {
                    be = bs = cur;
                } else {
                    be.next = cur;
                    be = cur;
                }
            } else {
                if (as == null) {
                    ae = as = cur;
                } else {
                    ae.next = cur;
                    ae = cur;
                }
            }
            cur = cur.next;
        }
        
        // 如果小值链表为空,直接返回大值链表
        if (bs == null) return as;
        
        be.next = as; // 连接两个链表
        if (as != null) {
            ae.next = null; // 关键:断开尾部,防止成环
        }
        return bs;
    }
}

2. 链表的回文结构

题目要求:判断链表是否为回文,空间复杂度需为 O(1)。

思路分析: 双指针法无法直接反向遍历单链表,因此采用'找中点 + 反转后半段'的策略。

  1. 使用快慢指针找到链表中间节点。
  2. 从中间节点开始,反转后半部分链表。
  3. 同时从头节点和反转后的头节点开始比较,若全部相等则为回文。

注意奇偶数节点的处理:偶数时 fast 最终为 null,奇数时为最后一个节点。比较时需小心处理相遇条件。

import java.util.Scanner;

class ListNode {
    int val;
    ListNode next;
    public ListNode(int val) { this.val = val; }
}

public class PalindromeList {
    public boolean chkPalindrome(ListNode A) {
        // 1. 找到中间节点
        ListNode fast = A, slow = A;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        
        // 2. 反转后半部分
        ListNode cur = slow.next;
        while (cur != null) {
            ListNode curN = cur.next;
            cur.next = slow;
            slow = cur;
            cur = curN;
        }
        
        // 3. 对比前后两部分
        while (A != slow) {
            if (A.val != slow.val) return false;
            // 偶数个节点的特殊判断
            if (A.next == slow) return true;
            A = A.next;
            slow = slow.next;
        }
        return true;
    }
}

3. 相交链表

题目要求:找出两个单链表相交的起始节点。

思路分析: 相交必然呈 Y 形。核心思路是对齐起点。先计算两链表长度 len1 和 len2,求出差值 len。让长链表指针先走 len 步,然后两指针同步前进,相遇点即为交点。

需注意空指针检查,以及长度差为负数时的指针交换逻辑。

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; next = null; }
}

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode pl = headA, ps = headB;
        int len1 = 0, len2 = 0;
        
        // 计算长度
        while (pl != null) { len1++; pl = pl.next; }
        while (ps != null) { len2++; ps = ps.next; }
        
        pl = headA; ps = headB;
        int len = len1 - len2;
        
        // 确保 pl 指向较长链表
        if (len < 0) {
            pl = headB; ps = headA;
            len = len2 - len1;
        }
        
        // 长链表先走 len 步
        while (len != 0) {
            pl = pl.next;
            len--;
        }
        
        // 同步前进直到相遇
        while (pl != ps) {
            pl = pl.next;
            ps = ps.next;
        }
        
        return pl; // 若无交点则返回 null
    }
}

4. 环形链表

题目要求:判断链表中是否存在环。

思路分析: 经典的 Floyd 判圈算法(快慢指针)。慢指针每次走一步,快指针每次走两步。如果存在环,快指针终将追上慢指针;如果不存在,快指针会先到达末尾。

想象两人在环形跑道上跑步,速度快的人迟早会套圈速度慢的人。关键在于循环终止条件 fast != null && fast.next != null。

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; next = null; }
}

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode fast = head, slow = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) return true;
        }
        return false;
    }
}

以上四个问题涵盖了链表操作的核心技巧。在实际编码中,指针的空值检查和边界情况往往是 Bug 的高发区,建议多画图辅助理解指针走向。

目录

  1. 链表中的经典面试题
  2. 1. 链表分割
  3. 2. 链表的回文结构
  4. 3. 相交链表
  5. 4. 环形链表
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • ComfyUI 快速部署指南:基于云原生环境的节点式 AI 绘图实践
  • Edict:基于三省六部制的 AI Agent 协作架构
  • 无需微调仅靠 Prompt 实现 LLM 持续学习新范式 CLOB 框架解析
  • PowerShell 中 Invoke-WebRequest 正确用法:避开参数匹配陷阱
  • Python GUI 可视化设计工具 tkinter-helper 介绍
  • AIGC 内容创作实战指南:基于 TRAE 框架与大语言模型提效方案
  • 信创国产化开发为何推荐使用 Java 语言
  • MySQL 中文乱码问题的原因及解决方案
  • Git 下载、安装与环境配置指南
  • 回溯算法核心原理与 Java 实现详解
  • AgentScope Java 实战:构建 AI 奶茶店应用
  • Windows 环境下 Git 安装与配置指南
  • 贪心算法进阶:摆动序列、递增三元组及股票买卖实战
  • AI 大模型驱动的软件开发全流程变革:从需求到运维
  • RxJava 源码深度解析:订阅流程与线程切换原理
  • Linux 远程服务器直接下载 HuggingFace 模型与数据集
  • AI 驱动 PCB 设计:对话式工具的效率与边界分析
  • LLaMA-Factory 大模型高效微调实战指南
  • LeetCode 92 链表区间反转:递归与哨兵节点实战
  • DeepSeek-V3 FP8 量化原理与工程实现

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online