Skip to content

Commit 00660b0

Browse files
committed
LC 1964. Find the Longest Valid Obstacle Course at Each Position (Rust DP)
1 parent 3eb5924 commit 00660b0

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ Solutions to LeetCode problems. The first column links to the problem in LeetCod
455455
| [1899. Merge Triplets to Form Target Triplet][lc1899] | 🟠 Medium | [![python](res/py.png)][lc1899py] |
456456
| [1926. Nearest Exit from Entrance in Maze][lc1926] | 🟠 Medium | [![python](res/py.png)][lc1926py] |
457457
| [1962. Remove Stones to Minimize the Total][lc1962] | 🟠 Medium | [![python](res/py.png)][lc1962py] |
458+
| [1964. Find the Longest Valid Obstacle Course at Each Position][lc1964] | 🔴 Hard | [![rust](res/rs.png)][lc1964rs] |
458459
| [1971. Find if Path Exists in Graph][lc1971] | 🟢 Easy | [![python](res/py.png)][lc1971py] |
459460
| [1991. Find the Middle Index in Array][lc1991] | 🟢 Easy | [![python](res/py.png)][lc1991py] |
460461
| [1996. The Number of Weak Characters in the Game][lc1996] | 🟠 Medium | [![python](res/py.png)][lc1996py] |
@@ -1468,6 +1469,8 @@ Solutions to LeetCode problems. The first column links to the problem in LeetCod
14681469
[lc1926py]: leetcode/nearest-exit-from-entrance-in-maze.py
14691470
[lc1962]: https://leetcode.com/problems/remove-stones-to-minimize-the-total/
14701471
[lc1962py]: leetcode/remove-stones-to-minimize-the-total.py
1472+
[lc1964]: https://leetcode.com/problems/find-the-longest-valid-obstacle-course-at-each-position/
1473+
[lc1964rs]: leetcode/find-the-longest-valid-obstacle-course-at-each-position.rs
14711474
[lc1971]: https://leetcode.com/problems/find-if-path-exists-in-graph/
14721475
[lc1971py]: leetcode/find-if-path-exists-in-graph.py
14731476
[lc1991]: https://leetcode.com/problems/find-the-middle-index-in-array/
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// 1964. Find the Longest Valid Obstacle Course at Each Position
2+
// 🔴 Hard
3+
//
4+
// https://leetcode.com/problems/find-the-longest-valid-obstacle-course-at-each-position/
5+
//
6+
// Tags: Array - Binary Search - Divide and Conquer - Binary Indexed Tree
7+
// - Segment Tree - Merge Sort - Ordered Set
8+
9+
struct Solution;
10+
impl Solution {
11+
/// Use dynamic programming, each subproblem can be seen as "the longest
12+
/// non-decreasing subsequence" but, if we use something similar to the
13+
/// LIS solution, it will run in O(n^2*log(n)), we can instead see that,
14+
/// for each index, we only need to find the longest sequence to the left
15+
/// where the last element is less than, or equal to the current element,
16+
/// because then we can append the current element. We could do this in
17+
/// O(n), resulting in O(n^2) overall time complexity, iterating over all
18+
/// the previous results but that can be optimized if we use an extra
19+
/// structure where we keep these previous results sorted and can binary
20+
/// search the insertion point.
21+
///
22+
/// Time complexity: O(n*log(n)) - We iterate over all the elements, for
23+
/// each, we do a binary search over the previous results that could be up
24+
/// to n.
25+
/// Space complexity: O(n) - The dp array uses n extra memory.
26+
///
27+
/// Runtime 112 ms Beats 100%
28+
/// Memory 3.7 MB Beats 100%
29+
pub fn longest_obstacle_course_at_each_position(obstacles: Vec<i32>) -> Vec<i32> {
30+
let mut dp = vec![std::i32::MAX; obstacles.len() + 1];
31+
let mut res = vec![0; obstacles.len()];
32+
let (mut l, mut mid, mut r);
33+
for (i, o) in obstacles.into_iter().enumerate() {
34+
(l, r) = (0, dp.len());
35+
while l < r {
36+
mid = l + (r - l) / 2;
37+
if dp[mid] <= o {
38+
l = mid + 1;
39+
} else {
40+
r = mid;
41+
}
42+
}
43+
res[i] = l as i32 + 1;
44+
dp[l] = o;
45+
}
46+
res
47+
}
48+
}
49+
50+
// Tests.
51+
fn main() {
52+
let tests = [
53+
(vec![2, 2, 1], vec![1, 2, 1]),
54+
(vec![1, 2, 3, 2], vec![1, 2, 3, 3]),
55+
(vec![3, 1, 5, 6, 4, 2], vec![1, 1, 2, 3, 2, 2]),
56+
];
57+
for t in tests {
58+
assert_eq!(Solution::longest_obstacle_course_at_each_position(t.0), t.1);
59+
}
60+
println!("\x1b[92m» All tests passed!\x1b[0m")
61+
}

0 commit comments

Comments
 (0)