206. 反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2]
输出:[2,1]
示例 3:
输入:head = []
输出:[]
提示:
链表中节点的数目范围是 [0, 5000]
-5000 <= Node.val <= 5000
进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
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) {
// 方法一:双指针法(不带虚拟头结点)迭代法
// 思路:使用指针temp和pre在遍历链表的过程中,使两个结点的指向关系相反。
// 时间O(n), 空间O(1)
ListNode temp = null;
ListNode cur = head;
ListNode pre = null;
while (cur != null) {
temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
// 方法二:双指针法(虚拟头结点)迭代法
// 时间O(n), 空间O(1)
ListNode dummyHead = new ListNode(-1, head);
ListNode temp = null;
ListNode cur = dummyHead.next;
dummyHead.next = null;
while (cur != null) {
temp = cur.next;
cur.next = dummyHead.next;
dummyHead.next = cur;
cur = temp;
}
return dummyHead.next;
// 方法三:递归法
// 思路:与不带虚拟头结点的双指针法逻辑一样。
// 时间O(n), 空间O(1)
//return语句等价于双指针中的
//ListNode* cur = head;
//ListNode* pre = nullptr;
return reverse(null, head);
}
private ListNode reverse(ListNode pre, ListNode cur) {
// 递归终止条件
if (cur == null)
return pre;
// 单层递归逻辑
ListNode temp = cur.next;
cur.next = pre;
//等价于双指针中的
//pre = cur;
//cur = temp;
return reverse(cur, temp);
}
}