Nameless Site

But one day, you will stand before its decrepit gate,without really knowing why.

0%

反转链表

来源Leetcode第206题反转链表

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?


初次提交

一开始做的时候直接想着把链表形成一个闭环,然后通过这个闭环从最后一个结点逐一找到前一个结点,提交后用时击败了5.75%的用户,在二重循环里浪费了太多的时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static ListNode reverseList(ListNode head) {
if(head == null || head.next == null)
return head;
ListNode p1 = head;
ListNode p2;
int len = 1;
while (p1.next != null) {
p1 = p1.next;
len++;
}
p1.next = head;
ListNode newHead = p1;
for(int i = 0;i < len; i ++){
p2 = p1;
for(;p2.next != p1;p2 = p2.next);
p2.next = head;
p1.next = p2;
if(p2.next.next == p2){
p2.next.next = null;
break;
}
p1 = p1.next;
}
return newHead;
}

迭代

在遍历列表时,将当前节点的 next 指针改为指向前一个元素。由于节点没有引用其上一个节点,因此必须事先存储其前一个元素。在更改引用之前,还需要另一个指针来存储下一个节点。

1
2
3
4
5
6
7
8
9
10
11
public ListNode reverseList(ListNode head) {
ListNode p1 = null;
ListNode P2 = head;
while (P2 != null) {
ListNode nextTemp = P2.next;
P2.next = p1;
p1 = P2;
P2 = nextTemp;
}
return p1;
}

递归

来源题解

假设链表是[1, 2, 3, 4, 5]从最底层最后一个reverseList(5)来看

  • 返回了5这个节点
  • reverseList(4)中
  • p为5
  • head.next.next = head 相当于 5 -> 4
  • 现在节点情况为 4 -> 5 -> 4
  • head.next = null,切断4 -> 5 这一条,现在只有 5 -> 4
  • 返回(return)p为5,5 -> 4
  • 返回上一层reverseList(3)
  • 处理完后返回的是4 -> 3
  • 依次向上
1
2
3
4
5
6
7
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;
}