LeetCode 例题精讲 | 01 反转链表:如何轻松重构链表

LeetCode高频题指南:Top 100面试题精解 算法与数据结构是计算机科学的核心基础,其中LeetCode作为技术面试的黄金标准,其高频题目往往反映了行业最新考察趋势。本文基于硅谷一线科技公司的真实面试数据,通过权重评分公式精选出最具代表性的100道题目,覆盖数组、链表、动态规划等核心知识点。特别针对双指针、滑动窗口等高频解题模式,提供从暴力解法到最优实现的完整分析框架,帮助开发者建立面试官思维。掌握这些题目不仅能提升算法能力,更能深入理解时间空间复杂度的工程权衡,适用于准备FAANG级别公司面试的求职者。 阅读详情

本期例题:LeetCode 206 - Reverse Linked List(Easy)

反转一个单链表。

示例:

  • 输入: 1->2->3->4->5->NULL

  • 输出: 5->4->3->2->1->NULL

反转链表这道题是我在阿里的面试中遇到的题目。它本身也是单链表题目中非常典型的一道,不少题目的解法以反转链表为基础。这篇文章将会包含:

  • 链表类题目的注意点
  • 链表遍历的基本框架
  • 本期例题:反转链表的解法
  • 相关题目

链表类题目的注意点

在面试中涉及到的链表类题目,一定都是单链表。虽然实际中双向链表使用较多,但单链表更适合作为面试题考察。

单链表这样一个相对“简陋”的数据结构,实际上就是为了考察面试者指针操作的基本功。很多题目需要修改指针链接,如果操作不当,会造成链表结点的丢失,或者出现错误的回路。

我们早在 C/C++ 编程课上就学过链表数据结构。你一定对各种链表的变体印象深刻,单链表、双链表、循环链表……但是在面试中,请忘记你记得的各种花哨样式,只使用最简单的单链表操作。面试官很可能不希望看到你的各种“奇技淫巧”:

  • 加入哑结点(即额外的链表头结点)可以简化插入操作,但面试官通常会要求你不要创建额外的链表结点,哑结点显然也属于额外的结点。
  • 使用 C/C++ 的二级指针可以让删除结点的代码非常精简,但如果面试官对此不熟悉的话,会看得一头雾水。

那么,如何才能简洁明了地解决单链表问题呢?实际上很多链表题目都是类型化的,都可以归结为链表的遍历,以及在遍历中做插入和删除操作。我们可以使用链表遍历的框架来解题。

链表遍历的基本框架

单链表操作的本质难度在哪里?相比于双向链表,单链表缺少了指向前一个结点的指针,所以在删除结点时,还需要持有前一个结点的指针。这让遍历过程变得麻烦了许多。

比较容易想到的方法是将遍历的指针指向“前一个结点”,删除结点时使用 p.next = p.next.next。但这个方法会带来一些心智负担:

  • 每次要查看的结点是 p.next,也就是下一个结点,别扭
  • 循环终止条件不是 p == null 而是 p.next == null,容易出错

不是很好的链表遍历方式,有一定心智负担

实际上,这就是单链表操作的复杂性所在。我们前面也否定了使用二级指针这样的高级技巧来简化操作的方法,那么,有没有更简单明了的遍历方式呢?答案是有的。这里隆重推荐我一直在使用的链表遍历框架:

当删除链表结点时,既需要访问当前结点,也需要访问前一个结点。既然这样,我们不妨使用两个指针来遍历链表,curr 指针指向当前结点,prev 指针指向前一个结点。这样两个指针的语义明确,也让你写出的代码更易理解。

更好的链表遍历框架,指针意义清晰易懂

用代码写出来,链表遍历的框架是这样的:

ListNode prev = null;
ListNode curr = head;
while (curr != null) {
    // 进行操作,prev 表示前一个结点,curr 表示当前结点
    if (prev == null) {
        // curr 是头结点时的操作
    } else {
        // curr 不是头结点时的操作
    }
    prev = curr;
    curr = curr.next;
}

在遍历的过程中,需要一直维护 prev 是 curr 的前一个结点。curr 是循环中的主指针,整个循环的起始和终止条件都是围绕 curr 进行的。prev 指针作为辅助指针,实际上就是记录 curr 的上一个值。

在每一轮遍历中,可以根据需要决定是否使用 prev 指针。注意 prev 可能为 null(此时 curr 是头结点),在使用前需要先进行判断。

使用两个指针让删除结点非常容易:待删除

使用两个指针让删除结点非常容易:已删除

下面,我们看一看如何用这个链表遍历的框架来解决本期的例题:反转链表。

本期例题:反转链表的解法

反转链表的题目会有一个隐藏的要求:不能创建新的链表结点,只是在原有结点上修改链表指针。这样的原地操作会比生成一个新的链表要难很多。

反转链表的目标:链表结点不变,修改链表指针

Step 1 套用框架

这道题实际上就是一个典型的链表的遍历-处理的操作,于是我们套用使用上面所讲的链表遍历框架。要反转链表,实际上就是要反转所有相邻结点之间的指针。那么,整体的代码框架应该是:

ListNode prev = null;
ListNode curr = head;
while (curr != null) {
    // 反转 prev 和 curr 之间的指针
    prev = curr;
    curr = curr.next;
}

可以看到,遍历的框架已经将整体的思路架构了出来,我们知道按照如此的方式一定能遍历到所有相邻的结点对,也知道遍历结束后循环一定能正常退出。接下来只需要关注每一步如何反转结点之间的指针即可。

Step 2 写好单步操作

单步操作是“反转 prev 和 curr 之间的指针”。这里涉及到指针指向的改变,需要小心指针丢失的问题。在思考的时候,要考虑到和前一步、后一步的链接。

假设现在遍历到了链表中部的某个结点。链表应该会分成两个部分: prev 指针之前的一半链表已经进行了反转;curr 之后的一半链表还是原先的顺序。这次循环将让 curr 的指针改为指向 prev,就将当前结点从后一半链表放进了前一半链表。

循环开始时,prev 和 curr 分别指向链表的前半部分和后半部分

将当前结点放入前一半链表

下一轮循环时,prev 和 curr 仍然分别指向链表的前半部分和后半部分

而头结点的特殊情况是,全部链表都还未进行反转,即前一半链表为空。显然 curr.next 应当置为 null。

当前结点为头结点时,前一半链表为空

将 curr.next 置空,当前结点成为前一半链表的唯一结点

将单步操作放入代码框架,我们就得到了一份初版的解题代码:

ListNode prev = null;
ListNode curr = head;
while (curr != null) {
    if (prev == null) {
        curr.next = null;
    } else {
        curr.next = prev;
    }
    prev = curr;
    curr = curr.next;
}

Step 3 细节处理

上面的代码已经基本上比较完整了,但是还存在着明显的错误,那就是存在指针丢失的问题。

我们使用 curr.next = prev 来反转指针,但这会覆盖掉 curr.next 本来存储的值。丢掉这个指针之后,链表的后续结点就访问不到了!

直接赋值 curr.next 是错误的,我们会丢掉指向下一个结点的指针

要解决指针丢失的问题也很简单,使用一个临时指针保存 curr 的下一个结点即可。如下图所示:

使用临时指针保存下一个结点,避免指针丢失问题

不过这样一来,我们遍历框架中更新指针的操作也要随之进行微调。框架本来就不是一成不变的,需要根据实际题目灵活调整。

根据以上两点的细节处理,我们修改得到完整版的代码:

ListNode reverseList(ListNode head) {
    ListNode prev = null;
    ListNode curr = head;
    while (curr != null) {
        ListNode cnext = curr.next;
        if (prev == null) {
            curr.next = null;
        } else {
            curr.next = prev;
        }
        prev = curr;
        curr = cnext;
    }
    return prev;
}

上述代码中,if 的两个分支实际上可以优化合并,这里为了清晰起见仍然保留分支。

总结

总结起来,我们解决这一类单链表问题时,遵循的步骤是:

  1. 判断问题是否为链表遍历-修改,套用链表遍历框架
  2. 思考单步操作,将代码加入遍历框架
  3. 检查指针丢失等细节

有很多更复杂的链表题目都以反转链表为基础。下面列出了 LeetCode 上几道相关的题目:

希望本文的讲解能让你在写链表类题目时更得心应手。

从2017年PayPal笔试卷看外企软件工程师实习笔试备考策略 软件工程师岗位的笔试考察不仅是刷题数量的积累,更是对算法与数据结构、语言基础、系统设计思维等核心能力的综合检验。对于目标外企暑期实习的同学而言,理解笔试背后的能力模型,远比盲目刷题更重要。笔试通常从标准化算法题入手,考察候选人在限时环境下独立解决问题的能力;进而通过语言与工程基础题区分是否具备真实项目经验;最后以简化的系统设计题评估工程思维。这类考察方式广泛适用于互联网、金融科技等领域的软件开发岗位,尤其像PayPal这类支付公司,业务场景天然与高并发、分布式系统紧密相关。熟悉这些考点权重与准备策略,能帮助 阅读详情

相关推荐

nmap、X-Scan漏洞扫描和Metasploit中用永恒之蓝漏洞入侵靶机并上传冰河

利用nmap、X-Scan扫描靶机的漏洞,在Metasploit中用扫描出的永恒之蓝漏洞入侵靶机,建立连接后上传冰河木马控制靶机,最后用冰河陷阱清除靶机的冰河木马,记一次完整的入侵控制实验。

m0_59302403的博客 4407

143. 重排链表

题目: 给定一个单链表 L:L0→L1→…→Ln-1→Ln , 将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→… 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 方法:双指针+快慢指针+翻转链表 1.快慢指针找到切分链表 2.翻转右半部分链表 3左右合并拼接,依次合并 函数代码: class Solution { public: void reorderList(ListNode* head) { if(!head||!head->next

chenmi123321的博客 177

Matlab安装Embedded Coder Support Package for Texas Instruments C2000 Processors教程

Matlab安装Embedded Coder Support Package for Texas Instruments C2000 Processors

m0_69133594的博客 2824

LeetCode翻转字符

如果一个由 ‘0’ 和 ‘1’ 组成的字符串,是以一些 ‘0’(可能没有 ‘0’)后面跟着一些 ‘1’(也可能没有 ‘1’)的形式组成的,那么该字符串是 单调递增 的。我们给出一个由字符 ‘0’ 和 ‘1’ 组成的字符串 s,我们可以将任何 ‘0’ 翻转为 ‘1’ 或者将 ‘1’ 翻转为 ‘0’。定义新变量来不断更新翻转次数,ndp0记录的是将所有的0都反转成1需要的次数,而ndp1则记录每次的最小值。动态规划问题,其实就是要想整个字符串翻转最小,那么就要每个子串都翻转最小。输入:s = “00110”

liyatjj的博客 817

电力抄表协议DL/T645和698.45到底有啥区别?一张图帮你选对协议

本文深入对比了电力抄表协议DL/T645和DL/T698.45的技术差异,从协议架构、报文结构、功能覆盖到实施成本进行全面分析。通过实际案例和数据,揭示698.45协议在通信效率、业务扩展性和长期成本上的优势,并提供清晰的选型决策流程图,帮助工程师根据具体需求选择最适合的电力抄表协议。

weixin_38168696的博客 401

代码复现——SymAgent:一种用于知识图谱复杂推理的神经符号自学习Agent框架

根据《SymAgent: A Neural-Symbolic Self-Learning Agent Framework for Complex Reasoning over Knowledge Graphs》(《SymAgent:一种用于知识图谱复杂推理的神经符号自学习Agent框架》)论文思路,简单复现代码,以实现SymAgent中的Agent-Planner和Agent-Executor模块。Agent-Planner利用大语言模型的归纳推理能力从知识图谱中提取符号规则,指导高效的问题分解。

qq_60040306的博客 1605

java实现的链表的反转

  /** * */ package com.test; /** * @author Administrator * */ public class Node { private Node next; private String value; /** * */ public Node(String value) { // TODO Auto-genera...

又是一天 188

打通ZYNQ的任督二脉:AXI_FIFO数据交互全解析

FIFO(First In First Out,先进先出)是一种经典的数据缓冲结构,就像排队买票一样,先来的人先得到服务。时钟域交叉(CDC):连接不同时钟频率的模块数据缓冲:平衡生产者和消费者的速度差异流量控制:防止数据丢失或溢出input clk,// 输入AXI4-Stream接口(从PS到PL)// 输出AXI4-Stream接口(从PL到PS)// 状态指示信号// 定义状态机状态// 数据缓存// 8个深度的缓存// 流水线处理寄存器。

QQ_778132974的博客 305

面试必备 | 不可不会的反转链表

来源:码农田小齐反转链表这题真的是面试非常喜欢考的了,这题看起来简单,但是能用两种方法一遍 bug free 也是不容易的,面试的时候可以筛下来一大批人,无论是对 junior 还是 s...

Java笔记虾 484

EMS案例:BMS传导发射超标整改案例

BMS作为新能源汽车的关键部件,其EMC性能直接影响整车的安全性和可靠性。本文通过一个实际的传导发射整改案例,详细展示了从问题定位、分析到解决方案实施的全过程。希望这些经验能够为从事类似产品设计的工程师提供有价值的参考,在未来的产品开发中避免类似问题,设计出更加可靠、稳定的BMS产品。EMC设计是一门结合理论与实践的艺术,只有通过不断积累经验、深入理解电磁场理论,并紧密结合实际应用场景,才能在复杂的电磁环境中设计出鲁棒性强的电子产品。

m0_56451176的博客 272

YOLOv11 改进入门篇 | 轻量级涨点技巧:GhostConv 替代普通卷积的实战指南

摘要: 本文介绍如何通过GhostConv改进YOLOv11,实现轻量化涨点。YOLOv11深度增加导致参数量、延迟和内存占用上升,GhostConv通过“本征特征+线性变换”策略,在精度几乎无损的情况下降低30%-50%计算量。文章详细解析GhostConv原理,对比普通卷积的参数量和FLOPs优势,并提供完整的代码级改造流程,包括模块实现、注册及网络配置。实验表明,该方法有效提升边缘端推理效率,适用于移动端等资源受限场景。

shrgegrb的博客 1655

leetcode 143. 重排链表(反转链表、重构链表、递归、容器)

题目描述: 给定一个单链表 L:L0→L1→…→Ln-1→Ln , 将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→… 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 思路: 1、先找到中间节点,然后翻转后半段,最后再插入到前半段 2、递归 3、使用容器存储 代码如下: 1、 class Solution { public: ListNode* reverse(ListNode *head){ ListNode *p1=NULL; L

peachzy的博客 286

Vivado ILA抓DDR信号(各种IO信号:差分、ISERDES、IOBUFDS等)

Vivado ILA抓DDR信号(各种IO信号:差分、ISERDES、IOBUFDS等)

千歌叹尽执夏的博客 1097

jdk8 list 反转_LeetCode 例题精讲 | 01 反转链表:如何轻松重构链表

本期例题:LeetCode 206 - Reverse Linked List(Easy) 反转一个单链表。示例: 输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL反转链表这道题是我在阿里的面试中遇到的题目。它本身也是单链表题目中非常典型的一道,不少题目的解法以反转链表为基础。这篇文章将会包含:...

weixin_39640417的博客 132

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

c++链表形参丢失_LeetCode 例题精讲 | 01 反转链表:如何轻松重构链表

本期例题:LeetCode 206 - Reverse Linked List(Easy) 反转一个单链表。示例: 输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL反转链表这道题是我在阿里的面试中遇到的题目。它本身也是单链表题目中非常典型的一道,不少题目的解法以反转链表为基础。这篇文章将会包含:...

weixin_33356544的博客 91

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

不使用链表的fcfs_LeetCode 例题精讲 | 01 反转链表:如何轻松重构链表

点击关注上方“五分钟学算法”,设为“置顶或星标”,第一时间送达干货。转自面向大象编程本期例题:LeetCode 206 - Reverse Linked List[1](Easy)反转一个单链表。示例:输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL反转链表这道题是我在阿里的面试中遇到...

weixin_39666496的博客 82

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

假设以带头结点的循环链表表示队列_LeetCode 例题精讲 | 01 反转链表:如何轻松重构链表

本期例题:LeetCode 206 - Reverse Linked List(Easy)反转一个单链表。示例:输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL反转链表这道题是我在阿里的面试中遇到的题目。它本身也是单链表题目中非常典型的一道,不少题目的解法以反转链表为基础。这篇文章将会包含:链表...

weixin_39544333的博客 132

肝了三天三夜!吴师兄的高频手撕算法合集来了!

点击上方“五分钟学算法”,选择“星标”公众号 重磅干货,第一时间送达 作者 |L的存在 来源 |我是程序员小贱 基础数据结构的融合是成为庞大系统的基石。比如 Redis 中的跳跃表,数据库索引B+树等,只有对基础的数据结构足够的熟悉才能更容易去理解稍微复杂的结构,就仿佛我们闯关打怪一样,一步一步解锁直到结局。 今天想和大家一起分享...

墨鱼菜鸡 855

腾讯校招笔试题解析:从数据结构到系统基础的全栈能力体检

在技术面试与校招笔试中,数据结构与算法始终是考察候选人逻辑思维与编码基本功的核心模块,而操作系统、计算机网络、数据库等知识则决定了工程师排查问题与系统设计的上限。理解这些基础概念的原理与应用场景,不仅是应对大厂笔试的关键,更是后端开发日常工作中不可或缺的能力。本文从二叉树遍历、动态规划建模、TCP握手机制、C++虚函数、MySQL索引等通用技术点切入,结合腾讯2017年开发工程师笔试试卷的题型分布与答题策略,剖析大厂笔试背后的考察逻辑,并给出模拟训练、时间分配、错题复盘等实践方法,帮助读者系统提升基础能力与

weixin_34408624的博客 505

2026大厂大模型/Agent面试题

1题目不是很全,因为不都是笔者的面试,都是笔者各个渠道(牛客,脉脉,boss直聘)刷到的,然后随缘汇总,帮助自己复习,也帮助大家复习。

weixin_44151034的博客 1749

C链表重构

/*这次重写主要是为了增加结构的通用性、为了照顾初学的朋友我保*留原来的代码,那个看起来更容易被初学者理解.代码中的mian函数*只是简单的测试,大家可以根据需要自行修改.*/————————————————lis.h——————————————#ifndef LIST_H#define LIST_H /*定义函数状态*/#ifndef OK#define ERR -1

学习与研究 1620

链表重构(两个经典例题)

题目 将链表{a1,b1,a2,b2,a3,b3…an,bn}转换为{a1,a2…an}、{bn,bn-1…b1}b为逆序(逆序使用头插法) 解题思路 #include <stdio.h> #include <stdlib.h> #include<stdbool.h> typedef int Elemtype; typedef struct LNode { Elemtype data; struct LNode *next; } LNode,*

weixin_46503238的博客 397

leetcode 143. Reorder List (链表重构顺序)

题目要求 给定一个单链表 L:L0→L1→…→Ln-1→Ln , 将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→… 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 解题思路 这道题很有价值,涉及到了链表的多项操作,真正的是一道顶三道,建议多练习几遍。猛的一看这道题真的是没什么思路啊!如何在链表进行每个孔插入一个节点?这是个问题,但是当你有了这个思想的时候,你就...

爱喝舒化奶的博客 339
上一篇: LeetCode 例题精讲 | A 前言
下一篇: LeetCode 例题精讲 | 10 二叉树直径:二叉树遍历中的全局变量
nettee
博客等级 码龄14年 15粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值