1、剑指 Offer 24. 反转链表
目录
一、题目
剑指 Offer 24. 反转链表 难度简单
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
限制:
0 <= 节点个数 <= 5000
注意:本题与主站 206 题相同:https://leetcode-cn.com/problems/reverse-linked-list/
二、解法
2.1、遍历法(双指针)
核心思想:
在访问各节点时修改其 next
引用指向。在此过程中,可借助辅助变量(指针)来保存当前节点的 next ,以此为基础遍历整个链表。
复杂度分析:
- 时间复杂度 O(N):遍历链表使用线性大小时间。
- 空间复杂度 O(1): 变量
pre
和cur
使用常数大小额外空间。
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
// 上一个节点
ListNode prev = null;
// 当前节点
ListNode cursor = head;
while (cursor != null) {
// 辅助变量 next , 用以保存当前节点指向的下一个结点.
ListNode next = cursor.next;
// 让当前节点
cursor.next = prev;
// 循环处理的关键, 让当前节点作为 prev , 让辅助变量 next 作为当节点, 并进入下一个循环
prev = cursor;
cursor = next;
}
// 当 cursor 为 null 时, 整个链表已经被反转过来了
return prev;
}
}
2.2、递归法
核心思想:
使用递归法遍历链表,当越过尾节点后终止递归,在回溯时修改各节点的 next
引用指向。
复杂度分析:
- 时间复杂度 O(N):遍历链表使用线性大小时间。
- 空间复杂度 O(N): 遍历链表的递归深度达到 N ,系统使用 O(N) 大小额外空间。
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
// 调用递归并返回
return recur(head, null);
}
private ListNode recur(ListNode cur, ListNode pre) {
System.out.println(cur);
// 当 cur 为 null 时, pre 指向尾结点, 此时将 pre 作为反转链表的表头,开始回溯.
if (cur == null) return pre;
// 递归调用函数, 此时将 root 看作是一个已经被反转过的链表的表头.
ListNode root = recur(cur.next, cur);
// 将当前节点的 next 指向上一个节点,也就是 prev
cur.next = pre;
// 将反转过的链表的表头传递返回给上一级
return root;
}
}