Skip to content

Commit 818297f

Browse files
committed
add MyMaxHeap and heap sort
1 parent b6f0101 commit 818297f

34 files changed

+289
-185
lines changed

.cargo/config.toml.example

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
# https://bevyengine.org/learn/book/getting-started/setup/#enable-fast-compiles-optional
22
# sudo pacman -S lld
33
[target.x86_64-unknown-linux-gnu]
4-
rustflags = ["-Clink-arg=-fuse-ld=lld", "-Zshare-generics=y"]
4+
rustflags = ["-Ctarget-cpu=znver2", "-Clink-arg=-fuse-ld=lld", "-Zshare-generics=y"]
55

6-
# brew install michaeleisel/zld/zld
7-
[target.x86_64-apple-darwin]
8-
rustflags = ["-C", "link-arg=-fuse-ld=/usr/local/bin/zld", "-Zshare-generics=y"]
9-
10-
# rustup component add llvm-tools-preview && cargo install binutils
11-
[target.x86_64-pc-windows-msvc]
12-
linker = "rust-lld.exe"
13-
rustflags = ["-Zshare-generics=y"]
6+
#zld在苹果上是「负优化」,还不如默认的ld
7+
#[target.x86_64-apple-darwin]
8+
#rustflags = ["-C", "link-arg=-fuse-ld=/usr/local/bin/zld", "-Zshare-generics=y"]
149

1510
[profile.dev]
1611
split-debuginfo = "unpacked"

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#cargo-features = ["edition2021"]
12
[package]
23
name = "leetcode-rust"
34
version = "0.1.1"

README.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ leetcode_solutions
306306
|696|[Count Binary Substrings](https://leetcode.com/problems/count-binary-substrings/)|[Rust](src/easy/leetcode_very_easy.rs)|
307307
|700|[Search in a Binary Search Tree](https://leetcode.com/problems/search-in-a-binary-search-tree/)|[Rust](src/binary_tree/search_val_or_range_in_bst.rs)|
308308
|702🔒|[Search in a Sorted Array of Unknown Size](https://leetcode.com/problems/search-in-a-sorted-array-of-unknown-size/)|[Python](https://github.com/pymongo/python_leetcode/blob/master/binary_search/binary_search_unknown_size_sorted_array.py)|binary_search_first, 倍增法|
309-
|703|[Kth Largest Element in a Stream](https://leetcode.com/problems/kth-largest-element-in-a-stream/)|[Rust](src/data_structure/heap/kth_largest_element_in_a_stream.rs), [Python](https://github.com/pymongo/python_leetcode/blob/master/collections/top_k_largest_stream_min_heap.py)|
309+
|703|[Kth Largest Element in a Stream](https://leetcode.com/problems/kth-largest-element-in-a-stream/)|[Rust](src/data_structure/heap/kth_largest_element_in_a_stream.rs)|
310310
|704|[Binary Search](https://leetcode.com/problems/binary-search/)|[Python](https://github.com/pymongo/python_leetcode/blob/master/binary_search/binary_search.py)|binary_search|
311311
|705|[Design HashSet](https://leetcode.com/problems/design-hashset/)|[Python](https://github.com/pymongo/python_leetcode/blob/master/linked_list/impl_hashmap.py)||
312312
|706|[Design HashMap](https://leetcode.com/problems/design-hashmap/)|[Python](https://github.com/pymongo/python_leetcode/blob/master/linked_list/impl_hashmap.py)||
@@ -668,8 +668,6 @@ lintcode_problems
668668
|412|[Candy](https://lintcode.com/problem/candy/)|leetcode_135|
669669
|415|[Valid Palindrome](https://lintcode.com/problem/valid-palindrome/)|[Python](https://github.com/pymongo/python_leetcode/blob/master/palindrome/valid_palindrome.py)|two_pointers|
670670
|417|[Valid number](https://lintcode.com/problem/valid-number/)|leetcode_65|
671-
|418|[Integer to Roman](https://lintcode.com/problem/integer-to-roman/)|leetcode_12|
672-
|419|[Roman to Integer](https://lintcode.com/problem/roman-to-integer/)|leetcode_13|
673671
|420|[Count And Say](https://lintcode.com/problem/count-and-say/)|leetcode_38|
674672
|423|[Valid Parentheses](https://lintcode.com/problem/valid-parentheses/)|leetcode_20|
675673
|425|[Letter Combinations of a Phone Number](https://lintcode.com/problem/letter-combinations-of-a-phone-number/)|leetcode_17|

benches/bench_sorting.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ extern crate test;
44
use leetcode_rust::code_snippets::sorting::{
55
bubble_sort, my_quick_sort, random_numbers_test_case, selection_sort,
66
};
7+
use leetcode_rust::data_structure::heap::my_max_heap::MyMaxHeap;
78

89
#[bench]
910
fn bench_bubble_sort(bencher: &mut test::Bencher) {
@@ -19,7 +20,14 @@ fn bench_selection_sort(bencher: &mut test::Bencher) {
1920
bencher.iter(|| {
2021
let mut nums = random_numbers_test_case();
2122
selection_sort(&mut nums);
22-
//assert!(nums.is_sorted());
23+
});
24+
}
25+
26+
#[bench]
27+
fn bench_my_heap_sort(bencher: &mut test::Bencher) {
28+
bencher.iter(|| {
29+
let nums = random_numbers_test_case();
30+
let _ = nums.into_iter().collect::<MyMaxHeap<_>>().into_sorted_vec();
2331
});
2432
}
2533

@@ -28,7 +36,17 @@ fn bench_my_quick_sort(bencher: &mut test::Bencher) {
2836
bencher.iter(|| {
2937
let mut nums = random_numbers_test_case();
3038
my_quick_sort(0, nums.len() - 1, &mut nums);
31-
//assert!(nums.is_sorted());
39+
});
40+
}
41+
42+
#[bench]
43+
fn bench_std_heap_sort(bencher: &mut test::Bencher) {
44+
bencher.iter(|| {
45+
let nums = random_numbers_test_case();
46+
let _ = nums
47+
.into_iter()
48+
.collect::<std::collections::BinaryHeap<_>>()
49+
.into_sorted_vec();
3250
});
3351
}
3452

@@ -38,7 +56,6 @@ fn bench_std_merge_sort(bencher: &mut test::Bencher) {
3856
let mut nums = random_numbers_test_case();
3957
#[allow(clippy::stable_sort_primitive)]
4058
nums.sort();
41-
//assert!(nums.is_sorted());
4259
});
4360
}
4461

src/bfs_dfs_backtracking/all_paths_from_source_to_target.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn dfs(
3030
graph: &[Vec<usize>],
3131
dest: usize,
3232
) {
33-
for &next in graph[*curr.last().unwrap()].iter() {
33+
for &next in &graph[*curr.last().unwrap()] {
3434
if visited[next] {
3535
continue;
3636
}

src/bfs_dfs_backtracking/letter_combinations_of_a_phone_number.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ fn test_letter_combinations() {
4444
"23",
4545
&["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"],
4646
)];
47-
for &(input, output) in &TEST_CASES {
47+
for (input, output) in TEST_CASES {
4848
assert_eq!(letter_combinations_bfs(input.into()), output);
4949
}
5050
}

src/bfs_dfs_backtracking/max_area_of_island.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const TEST_CASES: [(&[&[i32]], i32); 1] = [(
6161

6262
#[test]
6363
fn test_max_area_of_island() {
64-
for &(grid, max_area) in &TEST_CASES {
64+
for (grid, max_area) in TEST_CASES {
6565
let grid: Vec<Vec<i32>> = grid.iter().map(|each| each.to_vec()).collect();
6666
assert_eq!(max_area_of_island(grid), max_area);
6767
}

src/bfs_dfs_backtracking/subsets.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ fn subsets_bfs(nums: Vec<i32>) -> Vec<Vec<i32>> {
8787
last.push(Vec::with_capacity(0));
8888
for num in nums {
8989
let mut curr = last.clone();
90-
for each_curr in curr.iter_mut() {
90+
for each_curr in &mut curr {
9191
each_curr.push(num);
9292
}
9393
last.append(&mut curr);

src/binary_search/median_of_two_sorted_arrays.rs

+16-17
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl Solution {
1515
if len % 2 == 0 {
1616
(nums1[len / 2 - 1] + nums1[len / 2]) as f64 / 2_f64
1717
} else {
18-
nums1[len / 2] as f64
18+
f64::from(nums1[len / 2])
1919
}
2020
}
2121

@@ -123,8 +123,7 @@ fn find_median_sorted_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
123123
if len_a == 1 {
124124
let mut nums_b = nums2;
125125
let insert_index = match nums_b.binary_search(&nums1[0]) {
126-
Ok(index) => index,
127-
Err(index) => index,
126+
Ok(index) | Err(index) => index,
128127
};
129128
nums_b.insert(insert_index, nums1[0]);
130129
return (nums_b[len_b / 2] as f64 + nums_b[(len_b + 1) / 2] as f64) / 2_f64;
@@ -196,16 +195,16 @@ fn find_median_sorted_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
196195
return if total_len % 2 == 0 {
197196
if b_divider_right_index == 1 {
198197
// [1,2]、[3,4]
199-
(nums1[len_a - 1] + nums2[0]) as f64 / 2_f64
198+
f64::from(nums1[len_a - 1] + nums2[0]) / 2_f64
200199
} else {
201200
// [1,3]、[2,4,5,6]
202-
(nums2[b_divider_right_index - 2].max(nums1[len_a - 1])
203-
+ nums2[b_divider_right_index - 1]) as f64
201+
f64::from(nums2[b_divider_right_index - 2].max(nums1[len_a - 1])
202+
+ nums2[b_divider_right_index - 1])
204203
/ 2_f64
205204
}
206205
} else {
207206
// [1,2]、[3,4,5,6,7]
208-
nums2[b_divider_right_index - 2].max(nums1[len_a - 1]) as f64
207+
f64::from(nums2[b_divider_right_index - 2].max(nums1[len_a - 1]))
209208
};
210209
}
211210
a_left = a_divider_right_index + 1;
@@ -214,9 +213,9 @@ fn find_median_sorted_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
214213
}
215214
}
216215
if total_len % 2 == 0 {
217-
(a_divider_left.max(b_divider_left) + a_divider_right.min(b_divider_right)) as f64 / 2_f64
216+
f64::from(a_divider_left.max(b_divider_left) + a_divider_right.min(b_divider_right)) / 2_f64
218217
} else {
219-
a_divider_left.max(b_divider_left) as f64
218+
f64::from(a_divider_left.max(b_divider_left))
220219
}
221220
}
222221

@@ -248,17 +247,17 @@ fn move_divider_of_two_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
248247

249248
// 如果较短数组的长度是0,统一了较长数组长度是奇数偶数的情况
250249
if len_a == 0 {
251-
return (nums2[(len_b - 1) / 2] as f64 + nums2[len_b / 2] as f64) / 2_f64;
250+
return (f64::from(nums2[(len_b - 1) / 2]) + nums2[len_b / 2] as f64) / 2_f64;
252251
}
253252
// 如果较短数组的长度是1,则较短数组的分割线左边或右边会没有值,这是一种特殊的边界条件
253+
// FIXME leetcode的binary_search依然返回第一次出现的位置,但最新的rust已经改成如有重复则返回随机一个num[index]=target
254254
if len_a == 1 {
255255
let mut nums_b = nums2;
256256
let insert_index = match nums_b.binary_search(&nums1[0]) {
257-
Ok(index) => index,
258-
Err(index) => index,
257+
Ok(index) | Err(index) => index,
259258
};
260259
nums_b.insert(insert_index, nums1[0]);
261-
return (nums_b[len_b / 2] as f64 + nums_b[(len_b + 1) / 2] as f64) / 2_f64;
260+
return (f64::from(nums_b[len_b / 2]) + f64::from(nums_b[(len_b + 1) / 2])) / 2_f64;
262261
}
263262

264263
// 往后的情况,nums1和nums2的长度至少为2
@@ -326,9 +325,9 @@ fn move_divider_of_two_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
326325
// 如果分隔线已经在最左边,则让b_divider_left或a_divider_left等于i32的最小值,好让它在比较左边两个元素的最大值时不会被选中
327326
// 如果分隔线已经在最右边,则让b_divider_right或a_divider_right等于i32的最大值,好让它在比较右边两个元素的最小值时不会被选中
328327
if total_len % 2 == 0 {
329-
(a_divider_left.max(b_divider_left) + a_divider_right.min(b_divider_right)) as f64 / 2_f64
328+
f64::from(a_divider_left.max(b_divider_left) + a_divider_right.min(b_divider_right)) / 2_f64
330329
} else {
331-
a_divider_left.max(b_divider_left) as f64
330+
f64::from(a_divider_left.max(b_divider_left))
332331
}
333332
}
334333

@@ -394,8 +393,8 @@ fn my_binary_search_kth(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
394393
// median_left_items_count += half_k;
395394
}
396395
if (len1 + len2) % 2 == 0 {
397-
(nums1[i] + nums2[j]) as f64 / 2_f64
396+
f64::from(nums1[i] + nums2[j]) / 2_f64
398397
} else {
399-
nums1[i].min(nums2[j]) as f64
398+
f64::from(nums1[i].min(nums2[j]))
400399
}
401400
}

src/binary_tree/serde_binary_tree_to_leetcode_vec.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*! serialize or deserialize binary tree to leetcode vec format
22
leetcode binary tree vec format example: [3,9,20,null,null,15,7] or [3,9,20,#,#,15,7]
3+
https://support.leetcode.com/hc/en-us/articles/360011883654-What-does-1-null-2-3-mean-in-binary-tree-representation-
34
*/
45
use super::{Rc, RefCell, TreeLink, TreeNode};
56

src/bitwise/find_single_number.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn single_number_xor_solution(nums: Vec<i32>) -> i32 {
2222
/// single_number_2的bitwise解法要用状态机去理解,不方便背诵
2323
fn single_number_2_sum_solution(nums: Vec<i32>) -> i32 {
2424
let nums_set: std::collections::HashSet<i64> =
25-
nums.clone().into_iter().map(|num| num as i64).collect();
25+
nums.clone().into_iter().map(i64::from).collect();
2626
let nums_set_sum = nums_set.into_iter().sum::<i64>();
2727
let nums_sum = nums.into_iter().map(i64::from).sum::<i64>();
2828
((nums_set_sum * 3 - nums_sum) / 2) as i32

src/code_snippets/random_i32.rs

-19
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,3 @@ pub fn rand_range(min: i32, max: i32) -> i32 {
4141
// 一般只记忆这个简单的 用MOD生成一定范围内的随机数
4242
random_num % max + min
4343
}
44-
45-
#[derive(Clone)]
46-
pub struct CookieRaw {
47-
pub token: Option<String>,
48-
pub current_igbid: Option<String>,
49-
}
50-
51-
impl ToString for CookieRaw {
52-
fn to_string(&self) -> String {
53-
format!(
54-
"token={};current_igbid={}",
55-
self.token.clone().unwrap_or_default(),
56-
self.current_igbid.clone().unwrap_or_default()
57-
)
58-
}
59-
}
60-
61-
#[test]
62-
fn feature() {}

src/counter/anagrams.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn anagram_mappings(mut a: Vec<i32>, b: Vec<i32>) -> Vec<i32> {
4242
for (i, b) in b.into_iter().enumerate() {
4343
map.insert(b, i as i32);
4444
}
45-
for a in a.iter_mut() {
45+
for a in &mut a {
4646
*a = *map.get(a).unwrap();
4747
}
4848
a

src/counter/count_good_meals.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ fn count_pairs_permutation_solution(nums: Vec<i32>) -> i32 {
1818
counter.push(i64::from(value));
1919
}
2020
// unique.sort_unstable(); // 由于nums是有序的,插入counter时也是有序的,所以不用排序
21-
let n = unique.len();
21+
let unique_len = unique.len();
2222
let mut ret = 0_i64;
23-
for i in 0..n {
24-
for j in i..n {
23+
for i in 0..unique_len {
24+
for j in i..unique_len {
2525
if is_power_of_2(unique[i] + unique[j]) {
2626
if i == j {
2727
// math.comb(count, 2)

src/counter/count_num1_square_eq_two_num2_product.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn test_diagonal_sum() {
5151
(&[7, 7, 8, 3], &[1, 2, 9, 7], 2),
5252
(&[4, 7, 9, 11, 23], &[3, 5, 1024, 12, 18], 0),
5353
];
54-
for &(nums1, nums2, res) in &TEST_CASES {
54+
for (nums1, nums2, res) in TEST_CASES {
5555
assert_eq!(num_triplets(nums1.to_vec(), nums2.to_vec()), res);
5656
}
5757
}

src/counter/number_of_equivalent_domino_pairs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fn num_equiv_domino_pairs(dominoes: Vec<Vec<i32>>) -> i32 {
1010
each[0] * 10 + each[1]
1111
} as usize;
1212
// 这里是C(n,2)的计数方式
13-
ret += counter[index] as i32;
13+
ret += i32::from(counter[index]);
1414
counter[index] += 1;
1515
}
1616
ret

src/counter/number_of_good_pairs.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn num_identical_pairs(nums: Vec<i32>) -> i32 {
1313
// array暂不支持into_iter, issue#66145
1414
counter
1515
.iter()
16-
.map(|&v| (v as i32 - 1) * v as i32 / 2)
16+
.map(|&v| (i32::from(v) - 1) * i32::from(v) / 2)
1717
.sum::<i32>()
1818
}
1919

@@ -43,11 +43,11 @@ fn number_of_good_pairs_v2(nums: Vec<i32>) -> i32 {
4343
*/
4444
fn number_of_good_pairs_v3(nums: Vec<i32>) -> i32 {
4545
let mut counter = std::collections::HashMap::<i32, u8>::with_capacity(nums.len());
46-
for num in nums.into_iter() {
46+
for num in nums {
4747
*counter.entry(num).or_default() += 1;
4848
}
4949
counter
5050
.into_iter()
51-
.map(|(_k, v)| (v as i32 - 1) * v as i32 / 2)
51+
.map(|(_k, v)| (i32::from(v) - 1) * i32::from(v) / 2)
5252
.sum::<i32>()
5353
}

src/data_structure/heap/kth_largest_element_in_a_stream.rs

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
如果富豪人数等于k则
66
如果新富豪比末位富豪更有钱,则踢掉最穷的富豪,新富豪入堆,重新heapify
77
否则小根堆维持不变
8+
9+
为什么用小根堆?
10+
「末尾淘汰制度」的思想,堆里面至多有k个元素,新来的元素至少要击败其中一个,才能进入堆
11+
说是小根堆,实际上存的是最大的几个,类似福布斯富豪榜,新来的必须足够大才能上榜
812
*/
913
use std::cmp::Reverse;
1014
use std::collections::BinaryHeap;
@@ -25,6 +29,7 @@ impl KthLargest {
2529
continue;
2630
}
2731
if num > min_heap.peek().unwrap().0 {
32+
// heapq.heapreplace
2833
min_heap.pop().unwrap();
2934
min_heap.push(Reverse(num));
3035
}

src/data_structure/heap/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
mod kth_largest_element_in_a_stream;
2+
#[allow(clippy::module_name_repetitions)]
3+
pub mod my_max_heap;
24
mod seat_reservation_manager;
35
mod single_threaded_cpu;
46
mod top_k_frequent_elements;

0 commit comments

Comments
 (0)