Skip to content

Commit e863518

Browse files
committed
LC 1671. Minimum Number of Removals to Make Mountain Array (Rust)
1 parent 1c13ed9 commit e863518

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ to the solution in this repository.
592592
| [1658. Minimum Operations to Reduce X to Zero][lc1658] | 🟠 Medium | [![python](res/py.png)][lc1658py] [![rust](res/rs.png)][lc1658rs] |
593593
| [1662. Check If Two String Arrays are Equivalent][lc1662] | 🟢 Easy | [![python](res/py.png)][lc1662py] [![rust](res/rs.png)][lc1662rs] |
594594
| [1669. Merge In Between Linked Lists][lc1669] | 🟠 Medium | [![python](res/py.png)][lc1669py] |
595+
| [1671. Minimum Number of Removals to Make Mountain Array][lc1671] | 🔴 Hard | [![rust](res/rs.png)][lc1671rs] |
595596
| [1675. Minimize Deviation in Array][lc1675] | 🔴 Hard | [![python](res/py.png)][lc1675py] [![rust](res/rs.png)][lc1675rs] |
596597
| [1680. Concatenation of Consecutive Binary Numbers][lc1680] | 🟠 Medium | [![python](res/py.png)][lc1680py] |
597598
| [1684. Count the Number of Consistent Strings][lc1684] | 🟢 Easy | [![rust](res/rs.png)][lc1684rs] |
@@ -2090,6 +2091,8 @@ to the solution in this repository.
20902091
[lc1662rs]: leetcode/check-if-two-string-arrays-are-equivalent.rs
20912092
[lc1669]: https://leetcode.com/problems/merge-in-between-linked-lists/
20922093
[lc1669py]: leetcode/merge-in-between-linked-lists.py
2094+
[lc1671]: https://leetcode.com/problems/minimum-number-of-removals-to-make-mountain-array/
2095+
[lc1671rs]: leetcode/minimum-number-of-removals-to-make-mountain-array.rs
20932096
[lc1675]: https://leetcode.com/problems/minimize-deviation-in-array/
20942097
[lc1675py]: leetcode/minimize-deviation-in-array.py
20952098
[lc1675rs]: leetcode/minimize-deviation-in-array.rs
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// 1671. Minimum Number of Removals to Make Mountain Array
2+
// 🔴 Hard
3+
//
4+
// https://leetcode.com/problems/minimum-number-of-removals-to-make-mountain-array/
5+
//
6+
// Tags: Array - Binary Search - Dynamic Programming - Greedy
7+
8+
use std::i32;
9+
10+
struct Solution;
11+
impl Solution {
12+
/// Run LIS forward and backwards, then use the combined result to find peak candidates and
13+
/// compute the number of removals needed to make them into the mountain peak in constant time
14+
/// using the longest increasing sequence up to that index and the longest decreasing sequence
15+
/// from that index to the end of the vector.
16+
///
17+
/// Time complexity: O(n*log(n)) - Same as the LIS problem, but we run it twice.
18+
/// Space complexity: O(n) - The lis vectors that we store.
19+
///
20+
/// Runtime 0 ms Beats 100%
21+
/// Memory 2.18 MB Beats 100%
22+
pub fn minimum_mountain_removals(nums: Vec<i32>) -> i32 {
23+
// This function returns a vector of the lis that can be formed with the values in the
24+
// iterator received as a parameter.
25+
fn lis_at_idx<'a, I>(iter: I, n: usize) -> Vec<usize>
26+
where
27+
I: Iterator<Item = &'a i32>,
28+
{
29+
let mut dp = vec![i32::MIN; n + 1];
30+
let mut lis_at_idx = vec![1; n];
31+
let mut lis = 0;
32+
let (mut l, mut m, mut r);
33+
for (idx, &num) in iter.enumerate() {
34+
(l, r) = (0, lis + 1);
35+
while l < r {
36+
m = (l + r) / 2;
37+
if dp[m] >= num {
38+
r = m;
39+
} else {
40+
l = m + 1;
41+
}
42+
}
43+
dp[l] = num;
44+
lis = lis.max(l);
45+
lis_at_idx[idx] = lis;
46+
}
47+
lis_at_idx
48+
}
49+
50+
let n = nums.len();
51+
let forward = lis_at_idx(nums.iter(), n);
52+
let mut backwards = lis_at_idx(nums.iter().rev(), n);
53+
backwards.reverse();
54+
(0..n)
55+
.map(|idx| {
56+
if forward[idx] > 1 && backwards[idx] > 1 {
57+
1 + n - forward[idx] - backwards[idx]
58+
} else {
59+
usize::MAX
60+
}
61+
})
62+
.min()
63+
.unwrap() as i32
64+
}
65+
}
66+
67+
// Tests.
68+
fn main() {
69+
let tests = [
70+
(vec![1, 3, 1], 0),
71+
(vec![1, 2, 1, 2, 1, 2, 1], 4),
72+
(vec![1, 2, 3, 4, 5, 3, 1], 0),
73+
(vec![1, 3, 2, 1, 2, 3, 2, 1], 3),
74+
(vec![2, 1, 1, 5, 6, 2, 3, 1], 3),
75+
(vec![1, 2, 3, 2, 1, 2, 3, 4], 3),
76+
(vec![3, 10, 9, 8, 7, 8, 9, 10], 3),
77+
(vec![1, 2, 5, 3, 4, 5, 3, 1, 6, 8], 3),
78+
];
79+
println!("\n\x1b[92m» Running {} tests...\x1b[0m", tests.len());
80+
let mut success = 0;
81+
for (i, t) in tests.iter().enumerate() {
82+
let res = Solution::minimum_mountain_removals(t.0.clone());
83+
if res == t.1 {
84+
success += 1;
85+
println!("\x1b[92m✔\x1b[95m Test {} passed!\x1b[0m", i);
86+
} else {
87+
println!(
88+
"\x1b[31mx\x1b[95m Test {} failed expected: {:?} but got {}!!\x1b[0m",
89+
i, t.1, res
90+
);
91+
}
92+
}
93+
println!();
94+
if success == tests.len() {
95+
println!("\x1b[30;42m✔ All tests passed!\x1b[0m")
96+
} else if success == 0 {
97+
println!("\x1b[31mx \x1b[41;37mAll tests failed!\x1b[0m")
98+
} else {
99+
println!(
100+
"\x1b[31mx\x1b[95m {} tests failed!\x1b[0m",
101+
tests.len() - success
102+
)
103+
}
104+
}

0 commit comments

Comments
 (0)