• 算法训练 第二周


    二、反转链表

    在这里插入图片描述
    本题给我们了一个单链表的头节点head,要求我们把这个单链表的连接顺序进行逆置,并返回逆置后的链表头节点。

    1.头插法

    我们需要先创建一个新的头节点ph,然后遍历给出的单链表,把遍历到的每一个节点用头插法接到ph的后面,这样我们就可以得到一个反转后的链表了,最后返回ph的next即可。需要注意的是,在进行头插语句之前,我们需要把当前节点的下一个节点先存储起来,否则会导致遍历节点的next丢失,具体代码如下:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode() {}
     *     ListNode(int val) { this.val = val; }
     *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
     * }
     */
    class Solution {
        public ListNode reverseList(ListNode head) {
            if(head == null) {
                return null;
            }
            ListNode ph = new ListNode();
            ListNode p = head;
            ListNode n;
            while(p != null) {
                n = p.next;
                p.next = ph.next;
                ph.next = p;
                p = n;
            }
            return ph.next;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    复杂度分析
    • 时间复杂度:O(n),只需遍历一遍原链表即可。
    • 空间复杂度:O(1)。

    2.递归

    递归法的要点在于我们需要先假设我们要处理的这个节点之前的节点已经全部完成反转,然后对于这个节点,我们只需要将它的next指向它的上一个节点即可,或者说我们需要将指针指向的节点的next的next指向这个节点本身,具体代码如下:

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode() {}
     *     ListNode(int val) { this.val = val; }
     *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
     * }
     */
    class Solution {
        public ListNode reverseList(ListNode head) {
            if(head == null) {
                return null;
            }
            if(head.next == null) {
                return head;
            }
            ListNode prev = head.next;
            ListNode p = prev.next; 
            head.next.next = head;
            head.next = null;
            return process(prev,p);
        }
    
        public ListNode process(ListNode prev,ListNode p) {
            if(p == null) {
                return prev;
            }
            if(p.next == null) {
                p.next = prev;
                return p;
            }
            ListNode ph = process(p,p.next);
            p.next = prev;
            return ph;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    复杂度分析
    • 时间复杂度:O(n),需要遍历整个链表。
    • 空间复杂度:O(n),递归调用压栈的空间取决于原链表的长度。
  • 相关阅读:
    Linux下一键安装Python3&更改镜像源&虚拟环境管理技巧
    2022牛客暑期多校训练营5(BCDFGHK)
    给Mac加上点保险 AppleCare+问题解答
    NetSuite 10个用户参数
    网络层--IP协议
    【最有效】解决anaconda的虚拟环境重复目录问题
    Doping:使用精心设计的合成数据测试和评估异常检测器的技术
    pytorch深度学习入门
    docker系列6:docker安装redis
    基于51单片机十字路交通灯仿真_黄灯闪烁_正常模式+夜间模式+紧急模式
  • 原文地址:https://blog.csdn.net/Gatcher/article/details/132905349