Skip to content

Commit 4a1ae2e

Browse files
committed
solve 148 merge sort
1 parent 302fe02 commit 4a1ae2e

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,5 @@ mod n0143_reorder_list;
141141
mod n0144_binary_tree_preorder_traversal;
142142
mod n0145_binary_tree_postorder_traversal;
143143
mod n0146_lru_cache;
144+
mod n0147_insertion_sort_list;
145+
mod n0148_sort_list;

src/n0147_insertion_sort_list.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* [147] Insertion Sort List
3+
*
4+
* Sort a linked list using insertion sort.
5+
*
6+
* <ol>
7+
* </ol>
8+
*
9+
* <img alt="" src="https://upload.wikimedia.org/wikipedia/commons/0/0f/Insertion-sort-example-300px.gif" style="height:180px; width:300px" /><br />
10+
* <small>A graphical example of insertion sort. The partial sorted list (black) initially contains only the first element in the list.<br />
11+
* With each iteration one element (red) is removed from the input data and inserted in-place into the sorted list</small><br />
12+
*
13+
*
14+
* <ol>
15+
* </ol>
16+
*
17+
* Algorithm of Insertion Sort:
18+
*
19+
* <ol>
20+
* Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list.
21+
* At each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there.
22+
* It repeats until no input elements remain.
23+
* </ol>
24+
*
25+
* <br />
26+
* Example 1:
27+
*
28+
*
29+
* Input: 4->2->1->3
30+
* Output: 1->2->3->4
31+
*
32+
*
33+
* Example 2:
34+
*
35+
*
36+
* Input: -1->5->3->4->0
37+
* Output: -1->0->3->4->5
38+
*
39+
*
40+
*/
41+
pub struct Solution {}
42+
use super::util::linked_list::{ListNode, to_list};
43+
44+
// submission codes start here
45+
46+
// TODO; boring
47+
impl Solution {
48+
pub fn insertion_sort_list(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
49+
None
50+
}
51+
}
52+
53+
// submission codes end
54+
55+
#[cfg(test)]
56+
mod tests {
57+
use super::*;
58+
59+
#[test]
60+
fn test_147() {
61+
}
62+
}

src/n0148_sort_list.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/**
2+
* [148] Sort List
3+
*
4+
* Sort a linked list in O(n log n) time using constant space complexity.
5+
*
6+
* Example 1:
7+
*
8+
*
9+
* Input: 4->2->1->3
10+
* Output: 1->2->3->4
11+
*
12+
*
13+
* Example 2:
14+
*
15+
*
16+
* Input: -1->5->3->4->0
17+
* Output: -1->0->3->4->5
18+
*
19+
*/
20+
pub struct Solution {}
21+
use super::util::linked_list::{ListNode, to_list};
22+
23+
// submission codes start here
24+
25+
/*
26+
堆排序需要额外空间, 不行
27+
28+
快排:
29+
* 不行, 单链表要快排必须同时持有两个 mut 引用, 而 rust 里这是不可能的(不知道用 unsafe 行不行)
30+
* 不用 rust 的话应该是可行的, Lomuto-partition, 用一个慢指针记录 no_lager_than 位置
31+
32+
归并,有点慢, 每次切分要遍历找到切分点, 而且递归栈深度 O(logN) 也不算严格的 O(1) 空间
33+
34+
Rust 标准库的 std::collections::LinkedList 都没有实现 sort() 你敢信...
35+
36+
这题用 rust 解对我而言真的是 Hard 级而不是 Medium 级了...
37+
38+
这里也是前置知识不足, GG 了解到链表的最佳排序方式确实就是 merge-sort
39+
*/
40+
impl Solution {
41+
pub fn sort_list(mut head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
42+
let mut len = 0;
43+
let mut ptr = head.as_ref();
44+
while let Some(node) = ptr {
45+
len += 1;
46+
ptr = node.next.as_ref();
47+
}
48+
Solution::merge_sort(head, len)
49+
}
50+
51+
fn merge_sort(mut head: Option<Box<ListNode>>, len: i32) -> Option<Box<ListNode>> {
52+
if len < 2 {
53+
return head;
54+
}
55+
let mut next = head.as_mut();
56+
let mut i = 1;
57+
while i < len / 2 {
58+
next = next.unwrap().next.as_mut();
59+
i += 1;
60+
};
61+
let mut l2 = next.unwrap().next.take();
62+
let mut l1 = Solution::merge_sort(head, len/2);
63+
let mut l2 = Solution::merge_sort(l2, len - len/2);
64+
Solution::merge(l1, l2)
65+
}
66+
67+
fn merge(mut l1: Option<Box<ListNode>>, mut l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
68+
let mut dummy = Some(Box::new(ListNode::new(0)));
69+
let mut next = dummy.as_mut();
70+
loop {
71+
match (l1, l2) {
72+
(Some(mut node1), Some(mut node2)) => {
73+
let node = if node1.val > node2.val {
74+
// give back ownership
75+
l2 = node2.next.take(); l1 = Some(node1); node2
76+
} else {
77+
l1 = node1.next.take(); l2 = Some(node2); node1
78+
};
79+
next.as_mut().unwrap().next = Some(node);
80+
next = next.unwrap().next.as_mut();
81+
},
82+
(Some(mut node1), None) => {
83+
next.unwrap().next = Some(node1); break
84+
},
85+
(None, Some(mut node2)) => {
86+
next.unwrap().next = Some(node2); break
87+
},
88+
(None, None) => { break },
89+
}
90+
}
91+
dummy.unwrap().next
92+
}
93+
}
94+
95+
// submission codes end
96+
97+
#[cfg(test)]
98+
mod tests {
99+
use super::*;
100+
101+
#[test]
102+
fn test_148() {
103+
assert_eq!(Solution::sort_list(linked![4,2,1,3]), linked![1,2,3,4]);
104+
assert_eq!(Solution::sort_list(linked![-1,5,3,4,0]), linked![-1,0,3,4,5]);
105+
assert_eq!(Solution::sort_list(linked![]), linked![]);
106+
}
107+
}

0 commit comments

Comments
 (0)