• 力扣206 - 反转链表【校招面试高频考题】


    一、题目描述

    原题传送门
    给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

    示例 1:
    在这里插入图片描述

    输入:head = [1,2,3,4,5]
    输出:[5,4,3,2,1]

    示例 2:
    在这里插入图片描述

    输入:head = [1,2]
    输出:[2,1]

    示例 3:

    输入:head = []
    输出:[]

    提示:

    • 链表中节点的数目范围是 [0, 5000]
    • -5000 <= Node.val <= 5000

    二、思路分析

    好,看完题目的描述,我们来分析一下去求解这道题目

    • 对于本题,是校招面试中的高频考题,所以我要专门拿出来做讲解,这题的思路并不难,考验的是你对于链表结构的基本功,接下来我们一起来分析一下
    • 对于本题,我会讲解两种方式,一种是利用头插,一种是利用三指针迭代。两种方法的思路很相似,但是本质却不同,听我给你道来

    1、头插

    • 对于头插这一种方法,也就是将结点一一地插入到链表的头后,所以我们需要先去建立出一个新的链表头,也就是我下面的这个【rhead】,通过去遍历原先的链表将这些结点一一转移过去即可
    • 但是在一个结点转移后下一个结点就找不到了,于是我们需要先去保存下一个结点

    在这里插入图片描述

    • 然后让【cur】的next去指向【rhead】,然后更新rhead和cur的值

    在这里插入图片描述

    • 然后我们通过保存下一个结点继续去进行一个头插

    在这里插入图片描述

    • 继续头插【2】结点,做结点指针的更新

    在这里插入图片描述

    • 同理

    在这里插入图片描述

    • 同上

    在这里插入图片描述

    • 此时当【cur == NULL】时,便结束一个遍历,然后新链表的头就是【rhead】,返回即可

    在这里插入图片描述

    • 可以看出,这其实并不算真正意义上的头插,对于头插法,大家最熟悉的应该是
    newnode->next = head->next;
    head->next = newnode;
    
    • 1
    • 2
    • 下面这种叫做带头结点的插入,我上面这种是不带头结点的,这个大家要做好区分
    • 代码在后面给出

    2、三指针迭代

    • 然后我们再来讲一讲三指针的迭代方法,这种方法不需要在去创建一个新的头结点指针,只需要在原先的链表上进行一个操作即可,也就是定义三个指针,一个【cur】指向当前链表的头,一个【nextNode】指向cur的next,一样是用于保存,还有一个则是【prev】,这个的话其实是用来算作链表最后一个结点指向空的,初始化就像下面这样

    在这里插入图片描述

    • 然后执行一个循环的逻辑,将【cur->next = prev】,让原本的头【cur】作为反转后新链表的尾巴,接着就是进行的一个迭代操作,首先将【cur】当前的值给到【prev】,然后将【nextNode】当前的值给到【cur】,然后让【nextNode】继续向下,这个时候其实就进行了一个迭代的操作

    在这里插入图片描述

    • 然后继续做翻转,让【cur->next】指向prev

    在这里插入图片描述

    • 同理

    在这里插入图片描述

    在这里插入图片描述

    • 可以看到,当这个【cur == NULL】时,整个链表便完成了一个翻转,此时便结束循环迭代的逻辑

    在这里插入图片描述

    • 然后可以看到,此时新链表的头并不是【cur】,而是【prev】,所以最后应该返回【prev】
    • 代码一样在下一模块给出

    三、整体代码展示【需要自取】

    1、头插

    这里展示一下整体代码,将上面我们的解说进行代码的一个转化

    class Solution {
    public:
        ListNode* reverseList(ListNode* head) {
            ListNode* cur = head;
            ListNode* rhead = NULL;
            while(cur)
            {
                ListNode* nextNode = cur->next;     //优先保存cur的next结点
                //头插
                cur->next = rhead;
                rhead = cur;
    
                cur = nextNode;
            }
            return rhead;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2、三指针迭代

    class Solution {
    public:
        ListNode* reverseList(ListNode* head) {
            if(head == NULL)
                return NULL;
            ListNode* prev = NULL;
            ListNode* cur = head;
            ListNode* nextNode = cur->next;
    
            while(cur)
            {
                cur->next = prev;
    
                //迭代
                prev = cur;
                cur = nextNode;
                if(nextNode)
                    nextNode = nextNode->next;
            }
            return prev;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    四、总结与提炼

    • 最后我们来总结一下本文所介绍的内容,本文讲解来一道力扣中有关链表翻转的题目,这道题目是校招笔试面试中有关链表章节非常高频的一道题目,大家下去一定要自己再画画图,分析一下,把这段代码逻辑自己实现一遍,才能更好地掌握

    以上就是本文所要描述的所有内容,感谢您对本文的观看,如有疑问请于评论区留言或者私信我都可以🍀

  • 相关阅读:
    【Python仿真】基于EKF的传感器融合定位
    搞定了 6 种分布式ID,分库分表哪个适合做主键?
    SpringMVC学习篇(十一)
    关于conda占C盘内存的问题
    打开时空隧道,重演云栖72小时云世界
    CSP-J 2019 入门级 第一轮 第17题
    5(6)-羧基四甲基罗丹明,CAS号:150347-56-1
    java第二十六课 —— java动态绑定机制 | 多态的应用(一)
    jfinal中如何使用过滤器监控Druid监听SQL执行?
    [附源码]java毕业设计学科类校外培训机构课程监管系统
  • 原文地址:https://blog.csdn.net/Fire_Cloud_1/article/details/127837540