Skip to content

Commit f71b494

Browse files
committed
find_median_sorted_arrays
1 parent cbac893 commit f71b494

File tree

5 files changed

+303
-1
lines changed

5 files changed

+303
-1
lines changed

src/find_median_sorted_arrays.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// 1. Find the longer one, we assume num1
2+
// 2. Look through the spliter index i (i belongs to left part)
3+
// for num1 between [m/2-n,m/2+n] (left closed, right closed) by bisection method
4+
// i start at m/2
5+
// 3. Find the complement index j (j belongs to left part) = (m + n - 1) / 2 - i
6+
// 4. Check whether i and j is valid, num1[i] <= num2[j+1] and num1[i+1] >= num2[j] etc.
7+
// If num1[i] > num2[j+1], i moves left. If num1[i+1] < num2[j], i moves right.
8+
// The index i moves by bisection method.
9+
// The index i moves left to (m / 2 + i - n) / 2, moves right to (m / 2 + n + i) / 2.
10+
11+
// The time complexity is O(log2(min(m,n)))
12+
// For m/2 it is always rounded down
13+
pub fn find_median_sorted_arrays(num1: &[usize], num2: &[usize]) -> Option<f32> {
14+
let m: usize = num1.len();
15+
let n: usize = num2.len();
16+
let longer: &[usize];
17+
let shorter: &[usize];
18+
let l_len: usize;
19+
let s_len: usize;
20+
if m >= n {
21+
longer = num1;
22+
shorter = num2;
23+
l_len = m;
24+
s_len = n;
25+
} else {
26+
longer = num2;
27+
shorter = num1;
28+
l_len = n;
29+
s_len = m;
30+
}
31+
32+
let mut i: usize = l_len / 2;
33+
let mut j: usize = 0;
34+
let mut done = false;
35+
36+
while !done {
37+
j = (m + n - 1) / 2 - i;
38+
if j > 0 {
39+
j - 1;
40+
}
41+
let c1: bool = j == s_len - 1 || longer[i] <= shorter[j + 1];
42+
let c2: bool = i == l_len - 1 || longer[i + 1] >= shorter[j];
43+
if c1 && c2 {
44+
done = true;
45+
} else if c2 {
46+
// move left
47+
if i > 1 {
48+
i = (m / 2 + i - n) / 2;
49+
} else {
50+
i = 0;
51+
}
52+
} else {
53+
// move right
54+
if i == l_len - 2 {
55+
i = l_len - 1;
56+
} else {
57+
i = (m / 2 + n + i) / 2;
58+
}
59+
}
60+
}
61+
62+
if (l_len + s_len) % 2 == 1 {
63+
if shorter[j] > longer[i] {
64+
if shorter[j] > longer[i - i] {
65+
return Some(longer[i] as f32);
66+
} else if shorter[j] < longer[i - 1] {
67+
return Some(shorter[j] as f32);
68+
} else {
69+
return None;
70+
}
71+
} else if shorter[j] < longer[i] {
72+
if longer[i - 1] > shorter[j] {
73+
return Some(longer[i - 1] as f32);
74+
} else if longer[i - 1] < shorter[j] {
75+
return Some(shorter[j] as f32);
76+
} else {
77+
return None;
78+
}
79+
} else {
80+
return None;
81+
}
82+
} else {
83+
if i >= 1 && longer[i - 1] > shorter[j] && longer[i] > shorter[j] {
84+
return Some((longer[i - 1] as f32 + longer[i] as f32) / 2.0);
85+
} else if j > 0 && shorter[j - 1] > longer[i] && shorter[j] > longer[i] {
86+
return Some((shorter[j - 1] as f32 + shorter[j] as f32) / 2.0);
87+
} else {
88+
return Some((longer[i] as f32 + shorter[j] as f32) / 2.0);
89+
}
90+
}
91+
}
92+
93+
#[cfg(test)]
94+
mod test {
95+
use super::find_median_sorted_arrays;
96+
97+
#[test]
98+
fn test_find_median_sorted_arrays() {
99+
assert_eq!(find_median_sorted_arrays(&[1, 3], &[2]), Some(2.0));
100+
101+
assert_eq!(find_median_sorted_arrays(&[2], &[1, 3]), Some(2.0));
102+
103+
assert_eq!(find_median_sorted_arrays(&[1, 2], &[3, 4]), Some(2.5));
104+
105+
assert_eq!(find_median_sorted_arrays(&[3, 4], &[1, 2]), Some(2.5));
106+
107+
assert_eq!(find_median_sorted_arrays(&[3, 4], &[5]), Some(4.0));
108+
109+
assert_eq!(find_median_sorted_arrays(&[5], &[3, 4]), Some(4.0));
110+
111+
assert_eq!(find_median_sorted_arrays(&[3, 4, 5], &[5]), Some(4.5));
112+
113+
assert_eq!(find_median_sorted_arrays(&[5], &[3, 4, 5]), Some(4.5));
114+
115+
assert_eq!(find_median_sorted_arrays(&[1, 2], &[1, 2]), Some(1.5));
116+
117+
assert_eq!(find_median_sorted_arrays(&[1, 2, 3], &[1, 2, 3]), Some(2.0));
118+
119+
assert_eq!(find_median_sorted_arrays(&[1, 2, 3, 4], &[1, 2, 3]), None);
120+
121+
assert_eq!(find_median_sorted_arrays(&[1, 2, 3, 4], &[10, 11, 12, 13]),
122+
Some(7.0));
123+
124+
assert_eq!(find_median_sorted_arrays(&[10, 11, 12, 13], &[1, 2, 3, 4]),
125+
Some(7.0));
126+
127+
assert_eq!(find_median_sorted_arrays(&[1, 2, 3, 4], &[3, 6, 7, 8]),
128+
Some(3.5));
129+
130+
assert_eq!(find_median_sorted_arrays(&[3, 6, 7, 8], &[1, 2, 3, 4]),
131+
Some(3.5));
132+
133+
assert_eq!(find_median_sorted_arrays(&[3, 6, 7, 8, 11, 12, 18, 19],
134+
&[1, 2, 3, 4, 21, 22, 44]),
135+
Some(8.0));
136+
137+
assert_eq!(find_median_sorted_arrays(&[3, 6, 7, 8, 11, 12, 18, 19],
138+
&[1, 2, 3, 4, 21, 22, 44, 45]),
139+
Some(9.5));
140+
}
141+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// 1. Find the longer one, we assume num1
2+
// 2. Look through the spliter index i (i belongs to left part)
3+
// for num1 between [m/2-n,m/2+n] (left closed, right closed) by bisection method
4+
// i start at m/2
5+
// 3. Find the complement index j (j belongs to left part) = (m+n)/2-i
6+
// 4. Check whether i and j is valid, num1[i] <= num2[j+1] and num1[i+1] >= num2[j]
7+
// If num1[i] > num2[j+1], i moves left. If num1[i+1] < num2[j], i moves right.
8+
// The index i moves by bisection method.
9+
// The index i moves left to (m/2-n+i)/2, moves right to (m/2+n+i)/2.
10+
11+
// The time complexity is O(log2(min(m,n)))
12+
// For m/2 it is always rounded down
13+
pub fn find_median_sorted_arrays(num1: &[usize], num2: &[usize]) -> Option<f32> {
14+
let m: usize = num1.len();
15+
let n: usize = num2.len();
16+
let longer: &[usize];
17+
let shorter: &[usize];
18+
let l_len: usize;
19+
let s_len: usize;
20+
if m >= n {
21+
longer = num1;
22+
shorter = num2;
23+
l_len = m;
24+
s_len = n;
25+
} else {
26+
longer = num2;
27+
shorter = num1;
28+
l_len = n;
29+
s_len = m;
30+
}
31+
32+
let mut i: usize = l_len / 2;
33+
let mut j: usize = 0;
34+
let mut done = false;
35+
36+
while !done {
37+
j = (m + n - 1) / 2 - i;
38+
if j > 0 {
39+
j - 1;
40+
}
41+
let c1: bool = j == s_len - 1 || longer[i] <= shorter[j + 1];
42+
let c2: bool = i == l_len - 1 || longer[i + 1] >= shorter[j];
43+
if c1 && c2 {
44+
done = true;
45+
} else if c2 {
46+
// move left
47+
if i > 1 {
48+
i = (m / 2 + i - n) / 2;
49+
} else {
50+
i = 0;
51+
}
52+
} else {
53+
// move right
54+
if i == l_len - 2 {
55+
i = l_len - 1;
56+
} else {
57+
i = (m / 2 + n + i) / 2;
58+
}
59+
}
60+
}
61+
62+
if (l_len + s_len) % 2 == 1 {
63+
if shorter[j] > longer[i] {
64+
if shorter[j] > longer[i - i] {
65+
return Some(longer[i] as f32);
66+
} else if shorter[j] < longer[i - 1] {
67+
return Some(shorter[j] as f32);
68+
} else {
69+
return None;
70+
}
71+
} else if shorter[j] < longer[i] {
72+
if longer[i - 1] > shorter[j] {
73+
return Some(longer[i - 1] as f32);
74+
} else if longer[i - 1] < shorter[j] {
75+
return Some(shorter[j] as f32);
76+
} else {
77+
return None;
78+
}
79+
} else {
80+
return None;
81+
}
82+
} else {
83+
if i >= 1 && longer[i-1] > shorter[j] && longer[i] > shorter[j] {
84+
return Some((longer[i-1] as f32 + longer[i] as f32) / 2.0);
85+
} else if j > 0 && shorter[j-1] > longer[i] && shorter[j] > longer[i] {
86+
return Some((shorter[j-1] as f32 + shorter[j] as f32) / 2.0);
87+
} else {
88+
return Some((longer[i] as f32 + shorter[j] as f32) / 2.0);
89+
}
90+
}
91+
}
92+
93+
#[cfg(test)]
94+
mod test {
95+
use super::find_median_sorted_arrays;
96+
97+
#[test]
98+
fn test_find_median_sorted_arrays() {
99+
assert_eq!(find_median_sorted_arrays(&[1, 3], &[2]), Some(2.0));
100+
101+
assert_eq!(find_median_sorted_arrays(&[2], &[1, 3]), Some(2.0));
102+
103+
assert_eq!(find_median_sorted_arrays(&[1, 2], &[3, 4]), Some(2.5));
104+
105+
assert_eq!(find_median_sorted_arrays(&[3, 4], &[1, 2]), Some(2.5));
106+
107+
assert_eq!(find_median_sorted_arrays(&[3, 4], &[5]), Some(4.0));
108+
109+
assert_eq!(find_median_sorted_arrays(&[5], &[3, 4]), Some(4.0));
110+
111+
assert_eq!(find_median_sorted_arrays(&[3, 4, 5], &[5]), Some(4.5));
112+
113+
assert_eq!(find_median_sorted_arrays(&[5], &[3, 4, 5]), Some(4.5));
114+
115+
assert_eq!(find_median_sorted_arrays(&[1, 2], &[1, 2]), Some(1.5));
116+
117+
assert_eq!(find_median_sorted_arrays(&[1, 2, 3], &[1, 2, 3]), Some(2.0));
118+
119+
assert_eq!(find_median_sorted_arrays(&[1, 2, 3, 4], &[1, 2, 3]), None);
120+
121+
assert_eq!(find_median_sorted_arrays(&[1, 2, 3, 4], &[10, 11, 12, 13]),
122+
Some(7.0));
123+
124+
assert_eq!(find_median_sorted_arrays(&[10, 11, 12, 13], &[1, 2, 3, 4]),
125+
Some(7.0));
126+
127+
assert_eq!(find_median_sorted_arrays(&[1, 2, 3, 4], &[3, 6, 7, 8]),
128+
Some(3.5));
129+
130+
assert_eq!(find_median_sorted_arrays(&[3, 6, 7, 8], &[1, 2, 3, 4]),
131+
Some(3.5));
132+
133+
assert_eq!(find_median_sorted_arrays(&[3, 6, 7, 8, 11, 12, 18, 19],
134+
&[1, 2, 3, 4, 21, 22, 44]),
135+
Some(8.0));
136+
137+
assert_eq!(find_median_sorted_arrays(&[3, 6, 7, 8, 11, 12, 18, 19],
138+
&[1, 2, 3, 4, 21, 22, 44, 45]),
139+
Some(9.5));
140+
}
141+
}

src/length_of_longest_substring.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// By using HashSet as a sliding window,
2+
// checking if a character in the current can be done in O(1)O(1).
3+
14
use std::collections::VecDeque;
25

36
pub fn length_of_longest_substring(s: String) -> usize {
@@ -25,6 +28,11 @@ pub fn length_of_longest_substring(s: String) -> usize {
2528

2629
// Optimized
2730
// https://leetcode.com/articles/longest-substring-without-repeating-characters/
31+
// The above solution requires at most 2n steps.
32+
// In fact, it could be optimized to require only n steps.
33+
// Instead of using a set to tell if a character exists or not,
34+
// we could define a mapping of the characters to its index.
35+
// Then we can skip the characters immediately when we found a repeated character.
2836

2937
use std::collections::HashMap;
3038

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod two_sum;
22
pub mod add_two_numbers;
33
pub mod length_of_longest_substring;
4+
pub mod find_median_sorted_arrays;

src/two_sum.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
// Approach #1 (Brute Force)
2+
// Loop through each element x,
3+
// find if there is another value that equals to target - x
4+
// The time Complexity is O(n*n)
25
pub fn two_sum(nums: &[usize], target: usize) -> Option<[usize; 2]> {
36
let len = nums.len();
47
if len < 2 {
@@ -15,7 +18,15 @@ pub fn two_sum(nums: &[usize], target: usize) -> Option<[usize; 2]> {
1518
}
1619

1720
// Approach #2 (One-pass Hash Table)
18-
// https://leetcode.com/articles/two-sum/
21+
// Inspired from https://leetcode.com/articles/two-sum/
22+
// To improve the time complexity,
23+
// we need a more efficient way to check if the complement exists in the array.
24+
// If exist we need to look up its index.
25+
// The best way maintain a mapping of each element to its indexs? HashMap.
26+
// We reduce the look up time from O(n)O(n) to O(1)O(1) by trading space for speed.
27+
// While we iterate and inserting elements into the table,
28+
// we also look back to check if current element's complement already exists in the table.
29+
// If it exists, we have found a solution and return immediately.
1930

2031
use std::collections::HashMap;
2132

0 commit comments

Comments
 (0)