天天看点

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

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

1、双指针法

1.定义两个指针: pre 和 cur ;pre 在前 cur 在后。

2.每次让 pre 的 next 指向 cur ,实现一次局部反转

3.局部反转完成之后,pre 和 cur 同时往前移动一个位置

4.循环上述过程,直至 pre到达链表尾部

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

中心思想为:设置两个指针,一个在前一个在后,始终让前面结点的下一个结点指向后面的指针(走的慢的指针),这样当走的慢的指针到达最后一个结点时,链表被反转过来

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、递归法

本解答借鉴于编程狂想曲发布于力扣网的题解,且图片均由力扣网截图。仅用于个人笔记,若有侵权,请联系删除。

思路分析:

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

递归解题首先要做的就是明确递推公式的意义 ,在这里对于结点1来说,它只需要知道它之后的所有结点反转之后的结果就可以了(也就是说递推公式reverlist的含义是:把拿到的链表进行反转,然后返回新的头结点)

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

结点1之后的结点,经过递归公式reverseList处理之后的结果如下图:

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

到这里就可以写成如下代码了:

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

接下来要做的就是反转结点1,也就是将下图转换为结点1为最后一个结点的过程,但是此时的head结点并没有改变,反转之后的头结点是newnode,而不是原来的head。

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

反转结点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 到达链表的最后一个结点 .

数据结构-力扣206(反转链表笔记)
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)
           

继续阅读