⭐算法入门⭐《链表》简单02 —— LeetCode 206. 反转链表

🙉饭不食,水不饮,题必须刷🙉

C语言免费动漫教程,和我一起打卡!
🌞《光天化日学C语言》🌞

LeetCode 太难?先看简单题!
🧡《C语言入门100例》🧡

数据结构难?不存在的!
🌳《数据结构入门》🌳

LeetCode 太简单?算法学起来!
🌌《夜深人静写算法》🌌

一、题目

1、题目描述

  给定单链表的头节点 h e a d head head ,要求反转链表,并返回反转后的链表头。
  样例输入: [ 1 , 2 , 3 , 4 ] [1,2,3,4] [1,2,3,4]
  样例输出: [ 4 , 3 , 2 , 1 ] [4, 3, 2, 1] [4,3,2,1]

2、基础框架

  • c++ 版本给出的基础框架代码如下:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
    }
};
  • 这里引入了一种数据结构 链表 ListNode
  • 成员有两个:数据域val和指针域next
  • 返回的是链表头结点;

3、原题链接

LeetCode 206. 反转链表

二、解题报告

1、思路分析

  • 这个问题,我们可以采用头插法,即每次拿出第 2 个节点插到头部,拿出第 3 个节点插到头部,拿出第 4 个节点插到头部,… 拿出最后一个节点插到头部。
  • 于是整个过程可以分为两个步骤:删除第 i i i 个节点,将它放到头部,反复迭代 i i i 即可。
  • 如图所示:
  • 我们发现,图中的蓝色指针永远固定在最开始的链表头结点上,那么可以以它为契机,每次删除它的next,并且插到最新的头结点前面,不断改变头结点head的指向,迭代 n − 1 n-1 n1 次就能得到答案了。

2、时间复杂度

  • 每个结点只会被访问一次,执行一次头插操作,总共 n n n 个节点的情况下,时间复杂度 O ( n ) O(n) O(n)

3、代码详解

class Solution {
    ListNode *removeNextAndReturn(ListNode* now) {                 // (1) 
        if(now == nullptr || now->next == nullptr) {
            return nullptr;                                        // (2) 
        }
        ListNode *retNode = now->next;                             // (3) 
        now->next = now->next->next;                               // (4) 
        return retNode;
    }
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *doRemoveNode = head;                             // (5) 
        while(doRemoveNode) {                                      // (6) 
            ListNode *newHead = removeNextAndReturn(doRemoveNode); // (7) 
            if(newHead) {                                          // (8) 
                newHead->next = head;                              
                head = newHead;                
            }else {
                break;                                             // (9) 
            }
        }
        return head;
    }
};
  • ( 1 ) (1) (1) ListNode *removeNextAndReturn(ListNode* now)函数的作用是删除nownext节点,并且返回;
  • ( 2 ) (2) (2) 本身为空或者下一个节点为空,返回空;
  • ( 3 ) (3) (3) 将需要删除的节点缓存起来,供后续返回;
  • ( 4 ) (4) (4) 执行删除 now->next 的操作;
  • ( 5 ) (5) (5) doRemoveNode指向的下一个节点是将要被删除的节点,所以doRemoveNode需要被缓存起来,不然都不知道怎么进行删除;
  • ( 6 ) (6) (6) 没有需要删除的节点了就结束迭代;
  • ( 7 ) (7) (7) 删除 doRemoveNode 的下一个节点并返回被删除的节点;
  • ( 8 ) (8) (8) 如果有被删除的节点,则插入头部;
  • ( 9 ) (9) (9) 如果没有,则跳出迭代。

三、本题小知识

复杂问题简单化的最好办法就是将问题拆细,比如这个问题中,将一个节点取出来插到头部这件事情可以分为两步:
  1)删除给定节点;
  2)将删除的节点插入头部;


  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英雄哪里出来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值