Skip to content

Commit 3f42223

Browse files
committed
148
1 parent d479631 commit 3f42223

File tree

3 files changed

+119
-3
lines changed

3 files changed

+119
-3
lines changed

SUMMARY.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
* [98. Validate Binary Search Tree](leetCode-98-Validate-Binary-Search-Tree.md)
103103
* [99. Recover Binary Search Tree](leetcode-99-Recover-Binary-Search-Tree.md)
104104
* [100. Same Tree](leetcode-100-Same-Tree.md)
105-
* [101 题到 147题](leetcode-101-200.md)
105+
* [101 题到 148题](leetcode-101-200.md)
106106
* [101. Symmetric Tree](leetcode-101-Symmetric-Tree.md)
107107
* [102. Binary Tree Level Order Traversal](leetcode-102-Binary-Tree-Level-Order-Traversal.md)
108108
* [103. Binary Tree Zigzag Level Order Traversal](leetcode-103-Binary-Tree-Zigzag-Level-Order-Traversal.md)
@@ -149,4 +149,5 @@
149149
* [144. Binary Tree Preorder Traversal](leetcode-144-Binary-Tree-Preorder-Traversal.md)
150150
* [145*. Binary Tree Postorder Traversal](leetcode-145-Binary-Tree-Postorder-Traversal.md)
151151
* [146. LRU Cache](leetcode-146-LRU-Cache.md)
152-
* [147. Insertion Sort List](leetcode-147-Insertion-Sort-List.md)
152+
* [147. Insertion Sort List](leetcode-147-Insertion-Sort-List.md)
153+
* [148. Sort List](leetcode-148-Sort-List.md)

leetcode-101-200.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,6 @@
9090

9191
<a href="leetcode-146-LRU-Cache.html">146. LRU Cache</a>
9292

93-
<a href="leetcode-147-Insertion-Sort-List.html">147. Insertion Sort List</a>
93+
<a href="leetcode-147-Insertion-Sort-List.html">147. Insertion Sort List</a>
94+
95+
<a href="leetcode-148-Sort-List.html">148. Sort List</a>

leetcode-148-Sort-List.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# 题目描述(中等难度)
2+
3+
![](https://windliang.oss-cn-beijing.aliyuncs.com/148.jpg)
4+
5+
要求时间复杂度为 `O(nlogn)`,最常用的就是归并排序了。
6+
7+
# 解法一
8+
9+
归并排序需要一个辅助方法,也就是对两个有序链表进行合并,在 [21 题](https://leetcode.wang/leetCode-21-Merge-Two-Sorted-Lists.html) 已经讨论过。
10+
11+
至于归并排序的思想,这里就不多讲了,本科的时候用 `Scratch` 做过一个演示视频,感兴趣的可以参考 [这里](https://zhuanlan.zhihu.com/p/71647786),哈哈。
12+
13+
那就直接放代码了。因为归并排序是一半一半的进行,所以需要找到中点。最常用的方法就是快慢指针去找中点了。
14+
15+
```java
16+
ListNode dummy = new ListNode(0);
17+
dummy.next = head;
18+
ListNode fast = dummy;
19+
ListNode slow = dummy;
20+
while (fast != null && fast.next != null) {
21+
slow = slow.next;
22+
fast = fast.next.next;
23+
}
24+
```
25+
26+
上边的代码我加了一个 `dummy` 指针,就是想当节点个数是偶数的时候,让 `slow` 刚好指向前边一半节点的最后一个节点,也就是下边的状态。
27+
28+
```java
29+
1 2 3 4
30+
^ ^
31+
slow fast
32+
```
33+
34+
如果 `slow``fast` 都从 `head` 开始走,那么当 `fast` 结束的时候,`slow` 就会走到后边一半节点的开头了。
35+
36+
当然除了上边的方法,在 [这里](https://leetcode.com/problems/sort-list/discuss/46714/Java-merge-sort-solution) 看到,还可以加一个 `pre` 指针,让它一直指向 `slow` 的前一个即可。
37+
38+
```java
39+
// step 1. cut the list to two halves
40+
ListNode prev = null, slow = head, fast = head;
41+
42+
while (fast != null && fast.next != null) {
43+
prev = slow;
44+
slow = slow.next;
45+
fast = fast.next.next;
46+
}
47+
```
48+
49+
他们的目的都是一样的,就是为了方便的把两个链表平均分开。
50+
51+
```java
52+
public ListNode sortList(ListNode head) {
53+
return mergeSort(head);
54+
}
55+
56+
private ListNode mergeSort(ListNode head) {
57+
if (head == null || head.next == null) {
58+
return head;
59+
}
60+
ListNode dummy = new ListNode(0);
61+
dummy.next = head;
62+
ListNode fast = dummy;
63+
ListNode slow = dummy;
64+
//快慢指针找中点
65+
while (fast != null && fast.next != null) {
66+
slow = slow.next;
67+
fast = fast.next.next;
68+
}
69+
70+
ListNode head2 = slow.next;
71+
slow.next = null;
72+
head = mergeSort(head);
73+
head2 = mergeSort(head2);
74+
return merge(head, head2);
75+
76+
}
77+
78+
private ListNode merge(ListNode head1, ListNode head2) {
79+
ListNode dummy = new ListNode(0);
80+
ListNode tail = dummy;
81+
while (head1 != null && head2 != null) {
82+
if (head1.val < head2.val) {
83+
tail.next = head1;
84+
tail = tail.next;
85+
head1 = head1.next;
86+
} else {
87+
tail.next = head2;
88+
tail = tail.next;
89+
head2 = head2.next;
90+
}
91+
92+
}
93+
if (head1 != null) {
94+
tail.next = head1;
95+
}
96+
97+
if (head2 != null) {
98+
tail.next = head2;
99+
}
100+
101+
return dummy.next;
102+
103+
}
104+
105+
```
106+
107+
当然严格的说,上边的解法空间复杂度并不是 `O(1)`,因为递归过程中压栈是需要消耗空间的,每次取一半,所以空间复杂度是 `O(log(n))`
108+
109+
递归可以去改写成迭代的形式,也就是自底向上的走,就可以省去压栈的空间,空间复杂度从而达到 `O(1)`,详细的可以参考 [这里](https://leetcode.com/problems/sort-list/discuss/46712/Bottom-to-up(not-recurring)-with-o(1)-space-complextity-and-o(nlgn)-time-complextity)
110+
111+
#
112+
113+
[147 题](https://leetcode.wang/leetcode-147-Insertion-Sort-List.html) 一样,主要还是考察对链表的理解和排序算法的实现。

0 commit comments

Comments
 (0)