leetcode:面试题24 反转链表

题目来源

面试题24 反转链表
206. 反转链表

题目描述

在这里插入图片描述

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) {

    }
};

题目解析

链表逆序的本质,就是把每一个节点原本指向下一个节点的next指针倒转过来,指向它的前置节点
在这里插入图片描述

递归

  • 使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,记作 ret .
  • 此后,每次函数在返回的过程中,让当前结点的下一个结点的 next 指针指向当前节点。
  • 同时让当前结点的 next指针指向 NULL ,从而实现从链表尾部开始的局部反转
  • 当递归函数全部出栈后,链表反转完成。

在这里插入图片描述

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head == nullptr || head->next == nullptr){
            return head;
        }

        ListNode *ret = reverseList(head->next);
        head->next->next = head; // 我【head】的下一个节点【next】指向【next】指向我自己【head】
        head->next = nullptr;   // 我自己【head】指向【next】空【null】

        return ret;
    }
};

在这里插入图片描述

双指针(原地反转⭐)

  • 定义两个指针: front 和 rhead ;front 在前 rhead 在后。
  • 每次让 front 的 next指向 rhead ,实现一次局部反转
  • 局部反转完成之后, front 和 rhead 同时往前移动一个位置
  • 循环上述过程,直至 rhead 到达链表尾部
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head == nullptr){
            return nullptr;
        }
        ListNode *rHead = nullptr, *front = head;
        while (front != nullptr){
            ListNode *t = front->next;
            front->next = rHead;
            rHead = front;
            front = t;
        }
        return rHead;
    }
};

在这里插入图片描述

针对链表的某个节点,如果要把它的next指针倒转,至少需要三个节点。

让我们从链表头部开始,建立三个临时节点的引用,分别为p1,p2,p3。它们分别指向头节点、第二个节点、第三个节点。
在这里插入图片描述

实现链表逆序的完整步骤如下:

1.以p2节点为视角,把p2节点原本指向p3的next指针倒转,指向p1。
在这里插入图片描述
2.三个临时节点引用p1,p2,p3分别向后移动一格位置。
在这里插入图片描述
3.重复第1步的工作,以p2节点为视角,把p2节点原本指向p3的next指针倒转,指向p1。
在这里插入图片描述
4.重复第2步的工作,三个临时节点引用p1,p2,p3分别向后移动一格位置。
在这里插入图片描述
5.继续像这样子迭代下去,一直到p2是空为止。
在这里插入图片描述
6.最后,把head节点的next指向空,成为逆序链表的尾节点。并且把p1赋值给head,让p1所在的节点成为逆序链表的头节点。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

头插法(不推荐,面试写这个没分,笔试的时候用)

遍历已有链表,对每个元素实行头插法插入到一个新的链表当中从而完成逆序。

ListNode* reverseList(ListNode* head) {
    if(head == NULL){
        return NULL;
    }

    ListNode *dummy = new ListNode(head->val), *newNode;
    ListNode *iter = head;
    while (iter){
        newNode = new ListNode(iter->val);
        newNode->next = dummy->next;
        dummy->next = newNode;
        iter = iter->next;
    }

    return dummy->next;
};

扩展:双链表反转

class Code01_ReverseList{
    struct Node{
        int value;
        Node * next;
        Node(int data) : value(data){
        }
    };
    
    struct DoubleNode{
        int value;
        DoubleNode *prev;
        DoubleNode *next;
        
        DoubleNode(int data) : value(data){
            
        }
    };


public:
    //  head
    //   a    ->   b    ->  c  ->  null
    //   c    ->   b    ->  a  ->  null
    static Node* reverseLinkedList(Node* head){
        if(head == nullptr || head->next == nullptr){
            return head;
        }
        
        Node *pre = nullptr, *curr = head, *next = nullptr;
        while (curr != nullptr){
            next = curr->next;
            curr->next = pre;
            pre = curr;
            curr = next;
        }
        
        return pre;
    }

    static DoubleNode  *reverseDoubleList(DoubleNode  *head){
        if(head == nullptr || head->next == nullptr){
            return head;
        }

        DoubleNode *prev = nullptr, *curr = head, *next = nullptr;
        while (curr != nullptr){
            next = curr->next;
            curr->next = prev;
            curr->prev = next;
            prev = curr;
            curr = next;
        }
        
        return prev;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值