Leetcode刷题-206:反转链表

1.题目描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例1:

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

示例2:

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

示例3:

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

来源:力扣(LeetCode)

2.题目分析

2.1 牺牲空间重构链表

这道题就是个十分简单的节点方向操作题,不涉及什么复杂的算法。我们可以通过构造一个带有头结点的链表使用头插法来实现一个新的反向链表。以[1,2,3]为例演示如下
在这里插入图片描述

2.1 原地迭代修改

原地迭代修改就是在每次遍历链表时,让当前cur节点的next指针指向前一个节点(完成局部倒置)。不过这种局部修改会使得链表断开,所以我们必须在修改当前节点前将其next节点提前保存。在更改引用之前,还需要存储后一个节点。在完成一次迭代倒置之后分别向前移动cur指针和pre指针的位置,最后返回新的头指针pre。其核心代码如下所示

next = cur->next;
cur->next = prev;
prev = cur;
cur = next;

在这里插入图片描述

2.2 递归解决

2.2.1 为什么可以使用递归

我们首先需要明白链表与递归有着天然的亲和性;接下来我们来看反转链表的问题,对于链表来说我们可以将其拆分为两个部分(头节点head和其他部分),此时的头节点head不需要反转,我们只需要将头节点之后的链表的倒置链表尾部加上头节点head就完成了总体的倒置。对于头节点之后的局部链表可以进行类似的拆分工作,这样就形成了递归的解法。

2.2.2 递归解决

递归的思想在于将问题逐步分解。递归通常与栈相关联,这是因为递归本身就是一个逆向的操作,鉴于此我们可以借助递归的逆向操作将链表进行倒置。假设有链表 [1–>2–>3–>4] ,若以经完成部分转向,假设现在处于 [1-->2-->3<--4]的状态,那么我们此时要处理的就是节点2和3之间的关系,此时我们就需要让3的next指向2,2的next指向3的next
我们将具体的递归过程分为以下两个过程:以及

  • 其中的递就是一步一步将问题分解,也就是要处理1就要先处理2,要处理2就要先处理3,以此类推,总之就是要先处理最后一个节点4
  • 递完之后我们要归的话此时的顺序是逆的,此时我们可以趁机进行链表的局部反转。如在处理4结点的时候我们注意到其next为空也就是它是最后一个节点,那么4将会是新的首节点,此时我们回过头处理3,此时基于3将两个节点3和4进行倒置,以此类推逐步进行指针节点指向的节点和其下一个节点的倒置。
  • 需要注意的是递归都是需要确定递归终止条件的,在本题中因为在拆解链表到只要一个节点时间就可以不用倒置,所以我们选择边界条件为head == NULL || head->next == NULL)

在这里插入图片描述

3.题目解答

3.1 头插法重构链表解决

/**
 * 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* cur = head;
        ListNode* pre = new ListNode();
        ListNode* temp;
        while(cur!=nullptr){
            temp = cur->next;
            cur->next = pre->next;
            pre->next = cur;
            cur = temp;
        }
        cur = pre->next;
        delete(pre);
        return cur; 
    }
};

3.2 原地迭代反转

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr) {
            ListNode* next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
};

3.3 递归解法

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head == NULL || head->next == NULL){
            return head;
        }
        ListNode* nex = reverseList(head->next);
        head->next->next = head;
        head->next = NULL; 
        return nex;
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值