7 递归——206. 反转链表 ★

7 递归

206. 反转链表

给你单链表的头节点head,请你反转链表,并返回反转后的链表。
示例 1:
在这里插入图片描述
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

算法设计

可以充分利用原有的存储空间,通过修改指针实现单链表的就地逆置。相当于将所有的箭头反向,头指针指向原链表的尾部。如图所示。
在这里插入图片描述
反转链表可以采用迭代法和递归算法两种方法实现,原理是一样的,只是实现方式不同而已。

1. 迭代法

以上面单链表为例,展示单链表就地逆置过程。
(1)首先处理第一个节点,反转后该节点是单链表的尾节点,其next指针指向空。
在这里插入图片描述
特别注意:在修改指针之前,一定要用一个辅助指针,记录断点,否则后面这一部分就会遗失到外太空,再也找不到了。
因此可以设置3个指针:p、q、r,p指向前一个节点,q指向当前节点,r指向下一个节点(断点)。

  • 初始时,p = nullptr,q = head。
  • 如果q非空,修改q的next指向p,即q->next = p;在修改之前,一定要先用r记录断点,r = q->next。
    在这里插入图片描述
  • 然后p、q两个指针后移。
    在这里插入图片描述
    (2)反转下一个节点。如果q非空,重复4个操作:记录断点、反转指针、两个指针后移。
    r = q->next; //记录断点
    q->next = p; //反转指针
    p = q; //后移一位
    q = r; //后移一位

在这里插入图片描述
(3)当处理完最后一个节点时,q为空,p指向的节点为头节点,返回头指针p即可。
在这里插入图片描述

算法实现

// LeetCode206 反转链表
ListNode* reverseList(ListNode* head) { // 迭代法
    ListNode *p = nullptr,*q = head, *r; // 前一个节点,当前节点,下一个节点
    while (q) {
        r = q->next; //记录断点
        q->next = p; //反转指针
        p = q; //后移一位
        q = r; //后移一位
    }
    return p; //返回反转链表的头指针
}

2. 递归算法

设计递归函数三部曲:
(1)函数名和参数
定义递归函数名为reverseList(),因为要反转链表head,因此需要设计一个参数head。
(2)递归的结束条件
考虑特殊情况,如果链表为空(head = nullptr),或者只有一个节点(head->next = nullptr),则不需要反转链表,直接返回head即可。
(3)自调用
在函数内部调用自身,调用自身时函数名相同。可以宏观考虑,如果第一个节点不动,后面所有节点完成了反转操作,反转第一个节点之后的链表可以调用同名函数reverseList(head->next)实现。
在这里插入图片描述
只需要两个操作:① 将该链表尾节点和第一个节点链接;② 修改第一个节点的next为空即可。后面链表反转后的尾节点正是head->next,修改其next指针指向第一个节点,即head->next->next = head。再修改第一个节点的next为空,head->next = nullptr。
在这里插入图片描述
最后,返回新链表的头指针r,r是自调用reverseList(head->next)的返回值。

算法实现

// LeetCode206 反转链表
ListNode* reverseList(ListNode* head) { // 递归算法
    if (head == nullptr || head->next == nullptr) //递归出口
        return head;
    ListNode *r = reverseList(head->next); //递归调用
    head->next->next = head; //反转指针
    head->next = nullptr;
    return r; //返回反转链表的头指针
}

算法分析

迭代法和递归算法的时间复杂度均为O(n)。递归的空间复杂度为O(n),迭代法的空间复杂度为O(1)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

趣学算法

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

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

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

打赏作者

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

抵扣说明:

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

余额充值