数据结构-力扣206(反转链表笔记)

本文详细介绍了两种常见的链表反转方法:双指针法和递归法。双指针法通过两个指针,一个在前一个在后,逐步反转链表。递归法则是通过递归调用来实现链表反转,首先反转后继节点,再调整当前节点的指针完成反转。两种方法均涉及链表操作的关键技巧和注意事项。
摘要由CSDN通过智能技术生成

1、双指针法


1.定义两个指针: pre 和 cur ;pre 在前 cur 在后。
2.每次让 pre 的 next 指向 cur ,实现一次局部反转
3.局部反转完成之后,pre 和 cur 同时往前移动一个位置
4.循环上述过程,直至 pre到达链表尾部

作者:huwt链接:https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-shuang-zhi-zhen-di-gui-yao-mo-/来源:力扣(LeetCode)
中心思想为:设置两个指针,一个在前一个在后,始终让前面结点的下一个结点指向后面的指针(走的慢的指针),这样当走的慢的指针到达最后一个结点时,链表被反转过来

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* cur = NULL, *pre = head;
        while (pre != NULL) {
            ListNode* t = pre->next;
            pre->next = cur;
            cur = pre;
            pre = t;
        }
        return cur;
    }
};

作者:huwt
链接:https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-shuang-zhi-zhen-di-gui-yao-mo-/
来源:力扣(LeetCode)

2、递归法

本解答借鉴于编程狂想曲发布于力扣网的题解,且图片均由力扣网截图。仅用于个人笔记,若有侵权,请联系删除。
思路分析:
在这里插入图片描述
递归解题首先要做的就是明确递推公式的意义 ,在这里对于结点1来说,它只需要知道它之后的所有结点反转之后的结果就可以了(也就是说递推公式reverlist的含义是:把拿到的链表进行反转,然后返回新的头结点)
在这里插入图片描述
结点1之后的结点,经过递归公式reverseList处理之后的结果如下图:
在这里插入图片描述
到这里就可以写成如下代码了:

public ListNode reverseList(ListNode head) {
    // 调用递推公式反转head结点之后的所有节点
    ListNode newHead = reverseList(head.next);
}

接下来要做的就是反转结点1,也就是将下图转换为结点1为最后一个结点的过程,但是此时的head结点并没有改变,反转之后的头结点是newnode,而不是原来的head。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
反转结点1即将head指向的下一个结点的下一个结点(head的下一个结点指向的地址)指向head,然后将head结点的下一个结点指向NULL。
将反转head指向的结点的代码完善之后,得到如下代码:

public ListNode reverseList(ListNode head) {
    // 调用递推公式反转head结点之后的所有节点
    ListNode newHead = reverseList(head.next);
    head->next->next=head;
    head->next=NULL;
    //此处两句顺序不能调换,如果换过来,head->next=NULL;
    //那么head->next->next就不再有意义,报错!
    return newnode;
    }

递归调用完成之后,最重要的是判断递归终止条件。应该在head=NULL或者head->next=NULL时终止调用,因为在这两种情况下,反转之后的结果就是他自己。
完整代码如下:

public ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }

    // 调用递推公式反转当前结点之后的所有节点
    // 返回的结果是反转后的链表的头结点
    ListNode newHead = reverseList(head.next);
    head.next.next = head;
    head.next = null;
    return newHead;
}

/*作者:hardcore-aryabhata
链接:https://leetcode-cn.com/problems/reverse-linked-list/solution/yi-bu-yi-bu-jiao-ni-ru-he-yong-di-gui-si-67c3/
来源:力扣(LeetCode)*/

3、妖魔化的双指针

1.原链表的头结点就是反转之后链表的尾结点,使用 head 标记 .
2.定义指针 cur,初始化为 head.
3.每次都让 head 下一个结点的 next 指向 cur ,实现一次局部反转
4.局部反转完成之后,cur 和 head 的 next 指针同时 往前移动一个位置
循环上述过程,直至 cur 到达链表的最后一个结点 .

在这里插入图片描述

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == NULL) { return NULL; }
        ListNode* cur = head;
        while (head->next != NULL) {
            ListNode* t = head->next->next;
            head->next->next = cur;
            cur = head->next;
            head->next = t;
        }
        return cur;
    }
};

作者:huwt
链接:https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-shuang-zhi-zhen-di-gui-yao-mo-/
来源:力扣(LeetCode)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值