反转链表
题目
思路
这个很简单,我们使用三个指针,分别指向当前遍历到的结点、它的前一个结点以及后一个结点。
在遍历的时候,做当前结点的尾结点和前一个结点的替换。
方法一:迭代
假设存在链表 1 → 2 → 3 → Ø,我们想要把它改成 Ø ← 1 ← 2 ← 3。
在遍历列表时,将当前节点的 next 指针改为指向前一个元素。由于节点没有引用其上一个节点,因此必须事先存储其前一个元素。在更改引用之前,还需要另一个指针来存储下一个节点。不要忘记在最后返回新的头引用!
代码
迭代
/**
* 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;
while (head != null) {
ListNode nextTemp = head.next;
head.next = prev;
prev = head;
//这两步相当于指针反转
head = nextTemp;
}
return prev;
}
}
复杂度分析
时间复杂度:O(n),假设 nn 是列表的长度,时间复杂度是 O(n)O(n)。
空间复杂度:O(1)。
递归
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode p = reverseList(head.next);
head.next.next = head;
head.next = null;
return p;
}
时间复杂度:O(n),假设 nn 是列表的长度,那么时间复杂度为 O(n)O(n)。
空间复杂度:O(n),由于使用递归,将会使用隐式栈空间。递归深度可能会达到 nn 层。
以上的步骤是这样的理解
1 先把头结点之后的赋值给一个临时变量
2 把头结点之后的清空
3 把头结点赋值给后面的
4然后把临时变量赋值给前面的头结点