剑指 Offer II 024. 反转链表(206. 反转链表)

题目:

 

 

 

思路:

【1】使用辅助空间是我们最容易的想到的处理方式,先遍历一遍存起来,然后反转连起来(但明显不是最优的)。

【2】循环中不使用辅助空间的情况

需要定义两个指针,一个是tem临时存储,一个是pre头部节点的存储,加上本身的head(给予的树头节点)
如树为【5,4,3,2,1】
那么第一次循环head先为5
此时先记录下一个节点tmp = head.next; ,即将将4赋予了tem
此时5被单独了出来,对接上新链条的pre,
head.next = pre;  
pre = head; //此时新链条为【5】
然后head = tmp; 完美承接到下一个节点,可以进行第二次遍历

第二次循环head先为4
此时先记录下一个节点tmp = head.next; ,即将将3赋予了tem
此时4被单独了出来,对接上新链条的pre,
head.next = pre;  
pre = head; //此时新链条为【4,5】,而pre也指向4这个首节点
然后head = tmp; 完美承接到下一个节点,可以进行第二次遍历
....

 

【3】递归的方式

代码展示:

递归的方式:

//时间0 ms击败100%
//内存41.4 MB击败39.14%
//时间复杂度:O(n),其中 n 是链表的长度。需要对链表的每个节点进行反转操作。
//空间复杂度:O(n),其中 n 是链表的长度。空间复杂度主要取决于递归调用的栈空间,最多为 n 层。
class Solution {
    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;
    }
}

 

使用辅助空间的方式:

//时间1 ms击败4.34%
//内存41.2 MB击败68.75%
class Solution {
    public ListNode reverseList(ListNode head) {
        LinkedList<ListNode> queue = new LinkedList<ListNode>();
        ListNode res = new ListNode(-1);
        while (head != null){
            queue.add(head);
            head = head.next;
        }
        ListNode tem = res;
        while (!queue.isEmpty()){
            tem.next = queue.pollLast();
            tem = tem.next;
            //这一步是为了防止形成环,因为如果是链表【5,4,3,2,1】
            //在没有清除的时候,4和5的下一个指针相互指向对方会形成环
            tem.next = null;
        }
        return res.next;
    }
}

 

循环中不使用辅助空间的情况:

//时间0 ms击败100%
//内存41.5 MB击败27.75%
/**
 * 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) {
        ListNode tmp = null, pre = null;

        while(head != null) {
            // 暂存后继节点 cur.next
            tmp = head.next;
            // 修改 next 引用指向
            head.next = pre;
            // pre 暂存 cur
            pre = head;
            // cur 访问下一节点
            head = tmp;
        }
        return pre;
    }
}

 

posted @ 2023-03-03 11:48  忧愁的chafry  阅读(16)  评论(0编辑  收藏  举报