LeetCode 206.反转链表(C++)

题目地址:力扣

解法1:三指针法

要反转链表,那么从链表头结点开始,头结点的next要指向空,那么就需要一个后继节点来保存头结点的后一个节点。有后继节点那么也需要一个当前节点(用head也可以,但是为了清楚表明可以另外用一个当前节点)。考虑头结点的后一节点要指向头结点,因此还需要一个前置节点来保存之前的节点。

这种方法总共需要借助三个指针来实现,分别是记录当前节点,上一节点以及后一节点。

思路:只要后一节点不为空,那么

1、将后继节点指向当前节点的next,即保存当前节点的下一节点

2、将当前节点的next指向前置节点,即反转过程

3、将前置节点指向当前节点(当前节点变成了下一次操作的前置节点)

4、将当前节点指向后继节点,即两个节点指向相同

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *prevNode = nullptr;
        ListNode *currNode = head;
        ListNode *nextNode = head;
        
        while(nextNode != nullptr)
        {
            nextNode = currNode->next;
            currNode->next = prevNode;
            prevNode = currNode;
            currNode = nextNode;
        }
        return prevNode;
    }
};

解法2:头插法

思路也很简单,正向链表只需要用头插法就可以反转了,但是这就需要一个哨兵节点来用于头插,最后返回的也是哨兵节点的next

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        // 哨兵节点
        ListNode sentry(0);
        ListNode *nextNode = head;
        // 下一节点非空就执行头插操作
        while (nextNode != nullptr)
        {
            nextNode = head->next;
            head->next = sentry.next;
            sentry.next = head;
            head = nextNode;
        }
        return sentry.next;
    }
};

解法3:递归法

涉及到需要反转的,就可以想可以从后往前做,但是单链表不能找其头结点,所以只能是用递归的方式从后往前

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        // 只要当前节点为空或者当前节点的next为空,都返回当前节点
        if (head == nullptr || head->next == nullptr)
            return head;
        // 都不为空,那么就递归将原链表的尾节点带出来,赋给newHead
        ListNode *newHead = reverseList(head->next);
        // 当前节点的后继节点的next指针指向当前节点
        head->next->next = head;
        // 反转后原链表头结点的next应该为空,因此每次都把head的next置为空
        head->next = nullptr;
        return newHead;
    }
};

解法4:尾置递归法

思路:尾置递归和前面的递归有所不同,递归的返回不再是从递归的里面出来,而是进入下一层递归。这也就意味着链表是从前往后走的,那么改变next之前就需要存下next指向的地方,因此需要用一个新的节点来保存。同时这个递归函数应该接受两个参数,所以不能直接写在reverseList的里面。

class Solution {
public:
    ListNode* reverse(ListNode* prev, ListNode *curr) {
        ListNode *nextNode;
        // 当前节点为空,说明到了prev正好指向链尾节点(新链头)
        if (curr == nullptr)
            return prev;
        // 当前节点不空,就先存下当前节点的next,然后把当前节点的next指向prev
        nextNode = curr->next;
        curr->next = prev;
        // 递归执行下一个节点
        return reverse(curr, nextNode);
    }

    ListNode* reverseList(ListNode* head) {
        return reverse(nullptr, head);
    }
};

Accepted

  • 28/28 cases passed (8 ms)
  • Your runtime beats 48.56 % of cpp submissions
  • Your memory usage beats 21.96 % of cpp submissions (8.2 MB)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值