每日一题:反转链表

49 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情

题目链接

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

示例一 image.png

输入: head = {1,2,3,4,5}
输出: {5,4,3,2,1}

示例二 image.png

输入: head = {1,2}
输出: {2,1}

示例三

输入: head = {}
输出: {}

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

解题思路: (双指针)

我们只需要通过更改节点的next指针就可以反转整个链表,这样做的好处是不需要再单独创建一个链表,存放反转后的节点,减少了内存空间上的损耗。如下图所示:

image.png

因为反转链表需要遍历整个链表,我们可以通过双指针的方式来实现链表的反转

首先我们先定义一个per指针,用来指向头节点。再定义一个cur指针,初始化为null

image.png

现在要开始反转了,现将 per.nexttemp指针 保存下来,也就是保存住这个节点

image.png

per.next = cur,更改后,per指针指向的节点就变成了null,完成了第一个节点的反转

image.png

cur = per,完成 cur指针 的移动

image.png

per = temp,完成 per指针 的移动

image.png

接下来,就是循环走代码逻辑了,继续移动precur指针

image.png

最后,per指针 已经指向了null,循环结束,链表也反转完毕了。 cur指针就指向了新的头结点,我们直接返回就行

image.png

代码: (Java实现)

/**
 * 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 cur = null;
        ListNode per = head;
        ListNode temp = null;
        while (per != null) {
            temp = per.next;
            per.next = cur;
            cur = per;
            per = temp;
        }
        return cur;
    }
}

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

提交结果

image.png

解题思路: (递归)

递归从逻辑上来讲跟双指针一样,都是当cur为空的时候退出循环,不断的将cur指向per的过程

关键在于初始化的地方,在双指针中,cur = nullper = head都进行了初始化。其实递归也进行了初始化,只不过写法和双指针不同,看代码也能看出

代码: (Java实现)

/**
 * 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) {
        return reverse(null,head);//相当于初始化了per,cur
    }

    public ListNode reverse(ListNode per,ListNode cur) {
        if (cur == null) {
            return per;
        }

        ListNode temp = null;
        temp = cur.next;//先保存下一个节点
        cur.next = per;//进行反转
        per = cur;//更新cur,per的位置
        cur = temp;
        
        return reverse(per,cur);
    }
}

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

提交结果

image.png