每日leetcode

06-01 1037阅读

206. 反转链表 - 力扣(LeetCode)

题目

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

每日leetcode

输入:head = [1,2,3,4,5]

输出:[5,4,3,2,1]

示例 2:

每日leetcode

输入:head = [1,2]

输出:[2,1]

示例 3:

输入:head = []

输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 next = pre; if(follow == nullptr) break; pre = head; head = follow; follow = follow->next; } return head; } };

    递归

    /**
     * Definition for singly-linked list.
     * 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* changeDirection(ListNode* pre, ListNode* follow) {
            ListNode* tmp = follow->next;
            follow->next = pre;
            if(tmp == nullptr) return follow;
            else return changeDirection(follow, tmp);
        }
        ListNode* reverseList(ListNode* head) {
            if(head == nullptr) return nullptr;
            return changeDirection(nullptr, head);
        }
    };

    复杂度分析

    迭代

    • 时间复杂度:至多访问每个节点3次,所以时间复杂度是O(n)的。
    • 空间复杂度:O(1)。

      递归

      • 时间复杂度:O(n)。
      • 空间复杂度:等价于递归的栈空间,即O(n)。

        官方题解(墙裂推荐看看,实现的思路很妙!!!!)

        • 迭代的方法有优化的空间,中间的停步判断其实可以不用额外设计一个follow==nullptr来停步,只要保持维护一个cur指针,每次都将下一个节点存储在一个中间节点中,那么就可以直接通过cur指针是否为空判断是否停步了(甚至不用判断原链表是否为空这步操作了)。
        • 复现:
        • /**
           * Definition for singly-linked list.
           * 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) {
                  ListNode *pre = nullptr, *cur = head;
                  while(cur) {
                      ListNode *follow = cur->next;
                      cur->next = pre;
                      pre = cur;
                      cur = follow;
                  }
                  return pre;
              }
          };
        • 官解的递归总体的思路就是先深入到最后一个节点,然后从最后一个节点开始反转。
        • 首先考虑停步策略,只有当节点为空(本身的输入就是空的情况)或者节点没有后续节点时,到达链表的最尾端。
        • 然后考虑反转的部分,显然是先反转后面的节点,再开始处理当前节点。
        • 那么先往下做一层递归,然后再考虑当层节点的翻转,首先我们需要把后继节点翻转了再翻转前驱节点,否则后继节点将无法通过node->next获得,那么后继节点怎么进行反转呢?
        • 当后继节点为node->next时,若翻转了,其next节点将会变回node,那么我们便可以直接让node->next->next = node来实现后继节点指向当前节点的翻转;
        • 然后再翻转前驱节点,因为每一层的前驱节点的翻转都是有前一节点的后续节点翻转实现的,所以在这里我们可以不做处理。但是因为最后链表头需要指向nullptr,所以为了代码的简洁,我们不妨就将前驱节点全反转为nullptr,那么链表头因为没有前驱节点的递归没有指向nullptr的问题就解决了(amazing!好想法)。
        • 复现:
        • /**
           * Definition for singly-linked list.
           * 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) {
                  if(!head || !head->next) return head;
                  ListNode *tail = reverseList(head->next);
                  head->next->next = head;
                  head->next = nullptr;
                  return tail;
              }
          };
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码