143. 重排链表

题目描述

给定一个单链表 L 的头节点 head ,单链表 L 表示为:

1
L0 → L1 → … → Ln - 1 → Ln

请将其重新排列后变为:

1
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …

不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

输入输出

1
2
3
4
5
输入:head = [1,2,3,4]
输出:[1,4,2,3]

输入:head = [1,2,3,4,5]
输出:[1,5,2,4,3]

基本思路

方法一:

  • 链表不支持下标访问,所以无法随机访问链表中任意位置的元素。因此比较容易想到的一个方法是,利用线性表存储该链表,然后利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表即可。
  • 性能:
    • 时间复杂度:$O(N)$,其中 N 是链表中的节点数。
    • 空间复杂度:$O(N)$,其中 N 是链表中的节点数。主要为线性表的开销。

方法二:目标链表即为将原链表的左半端和反转后的右半端合并后的结果

  1. 找到原链表的中点(参考「876. 链表的中间结点」)
  2. 将原链表的右半端反转(参考「剑指 Offer 24. 反转链表」)
  3. 将原链表的两端合并
  4. 性能:
    1. 时间复杂度:$O(N)$,其中 N 是链表中的节点数。
    2. 空间复杂度:$O(1)$

java实现

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// 方法一
class Solution {
public void reorderList(ListNode head) {
if(head == null) return;
List<ListNode> list = new ArrayList<ListNode>();
ListNode node = head;
while(node != null){
list.add(node);
node = node.next;
}
int i = 0, j = list.size() - 1;
while(i < j){
list.get(i).next = list.get(j);
i++;
if(i == j) break;
list.get(j).next = list.get(i);
j--;
}
list.get(i).next = null;
}
}

// 方法二
class Solution {
public void reorderList(ListNode head) {
if(head == null) return;
ListNode midnode = middleNode(head);

ListNode p1 = head;
ListNode reverse_node = midnode.next;

midnode.next = null;

ListNode p2 = reverse(reverse_node);
mergeTwoLists(p1, p2);
}

public ListNode reverse(ListNode head){
ListNode cur = head, pre = null;
while(cur != null){
ListNode tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
return pre;
}

public ListNode middleNode(ListNode head){
// 返回1 2 3 4中的3结点
int cnt = 0;
ListNode node = head;
while(node != null){
cnt++;
node = node.next;
}
int findnode = cnt / 2;
node = head;
for(int i = 0; i < findnode; i++){
node = node.next;
}
return node;
}

public void mergeTwoLists(ListNode p1, ListNode p2){
ListNode p1_tmp, p2_tmp;
while(p1 != null && p2 != null){
p1_tmp = p1.next;
p2_tmp = p2.next;
p1.next = p2;
p1 = p1_tmp;
p2.next = p1;
p2 = p2_tmp;
}
}
}