题目
方法一-迭代(双指针)
遍历链表时,将当前节点的next指针改为指向前一个元素。由于节点没有引用其上一个节点,所以必须先存储其前一个元素,在更改指针方向之前,还需要另一个指针来存储下一个节点。
定义两个指针
p
r
e
pre
pre 和
c
u
r
cur
cur,初始时
p
r
e
pre
pre 指向 null,
c
u
r
cur
cur指向链表头节点。
每次让
c
u
r
cur
cur 的
n
e
x
t
next
next 指向
p
r
e
pre
pre,实现一次局部反转,然后两个指针共同往前走一步 ,重复上述过程直至
c
u
r
cur
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 pre = null;
ListNode cur = head;
while( cur != null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
}
- 时间复杂度: O ( n ) O(n) O(n),n 为链表长度
- 空间复杂度: O ( 1 ) O(1) O(1)
该方法还可以省一个指针,利用原本的链表头节点指针 head:
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null)return null;
ListNode cur = head;
while(head.next != null){
ListNode tmp = head.next.next;
head.next.next = cur;
cur = head.next;
head.next = tmp;
}
return cur;
}
}
方法二-递归
递推公式
设 F(n) 代表反转以
h
e
a
d
head
head 为头节点的单向链表,F(n-1) 代表反转以
h
e
a
d
.
n
e
x
t
head.next
head.next 为头节点的单向链表,则递推公式为:
F(n) = F(n-1) + 反转
h
e
a
d
head
head 和
h
e
a
d
.
n
e
x
t
head.next
head.next 之间的指向关系
反转
h
e
a
d
head
head 和
h
e
a
d
.
n
e
x
t
head.next
head.next 之间的指向关系,即执行
h
e
a
d
.
n
e
x
t
.
n
e
x
t
=
h
e
a
d
;
h
e
a
d
.
n
e
x
t
=
n
u
l
l
head.next.next=head; \ head.next=null
head.next.next=head; head.next=null
终止条件
h e a d = n u l l head=null head=null 或 h e a d . n e x t = n u l l head.next=null head.next=null
具体代码
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null)return head;
ListNode ret = reverseList(head.next);
head.next.next = head;
head.next = null;
return ret;
}
}
复杂度分析
- 时间复杂度:O(n),n 为链表长度
- 空间复杂度:O(n),需要的栈空间大小取决于递归深度,最多为 n 层