LeetCode每日一题(1964. Find the Longest Valid Obstacle Course at Each Position)

本文介绍了一种寻找最长障碍赛段的算法实现,通过给定的障碍物高度数组,算法能够找出每个位置出发时最长的有效障碍赛段长度。具体方法包括使用动态规划思想并结合二分查找技巧来优化解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

You want to build some obstacle courses. You are given a 0-indexed integer array obstacles of length n, where obstacles[i] describes the height of the ith obstacle.

For every index i between 0 and n - 1 (inclusive), find the length of the longest obstacle course in obstacles such that:

You choose any number of obstacles between 0 and i inclusive.
You must include the ith obstacle in the course.
You must put the chosen obstacles in the same order as they appear in obstacles.
Every obstacle (except the first) is taller than or the same height as the obstacle immediately before it.
Return an array ans of length n, where ans[i] is the length of the longest obstacle course for index i as described above.

Example 1:

Input: obstacles = [1,2,3,2]
Output: [1,2,3,3]

Explanation: The longest valid obstacle course at each position is:

  • i = 0: [1], [1] has length 1.
  • i = 1: [1,2], [1,2] has length 2.
  • i = 2: [1,2,3], [1,2,3] has length 3.
  • i = 3: [1,2,3,2], [1,2,2] has length 3.

Example 2:

Input: obstacles = [2,2,1]
Output: [1,2,1]

Explanation: The longest valid obstacle course at each position is:

  • i = 0: [2], [2] has length 1.
  • i = 1: [2,2], [2,2] has length 2.
  • i = 2: [2,2,1], [1] has length 1.

Example 3:

Input: obstacles = [3,1,5,6,4,2]
Output: [1,1,2,3,2,2]

Explanation: The longest valid obstacle course at each position is:

  • i = 0: [3], [3] has length 1.
  • i = 1: [3,1], [1] has length 1.
  • i = 2: [3,1,5], [3,5] has length 2. [1,5] is also valid.
  • i = 3: [3,1,5,6], [3,5,6] has length 3. [1,5,6] is also valid.
  • i = 4: [3,1,5,6,4], [3,4] has length 2. [1,4] is also valid.
  • i = 5: [3,1,5,6,4,2], [1,2] has length 2.

Constraints:

  • n == obstacles.length
  • 1 <= n <= 105
  • 1 <= obstacles[i] <= 107

比较难理解, 说是 Longest Increasing Subsequence 的问题, 下面是我自己想的一个例子:

obstacles = [1, 4, 5, 6, 2, 3]

lis = [1]
lis = [1, 4]
lis = [1, 4, 5]
lis = [1, 4, 5, 6]
lis = [1, 2, 5, 6]
lis = [1, 2, 3, 6]

当 obstacle 比 lis 最后的元素大的时候, 我们只需要简单的将 obstacle push 到 lis 中即可, 重点是如果 obstacle 比 lis 最后的元素小的话, 我们对 lis 进行二分搜索, 找到第一个比 obstacle 大的元素,并且用 obstacle 替换它, ans[i]就是找到的这个元素的 index + 1。之所以可以进行替换,是因为我们的替换不会影响既有元素的数量, 我们假设被替换的 obstacle 是 o, 替换的是 o1, 下一个是 n, 如果 n < o1, 那我们需要再将 o1 替换为 n, 如果 o1 < n < o, 此时如果 o 没有被替换的话, 我们需要用 n 来替换 o, 但是因为 o 已经被替换为 o1, […, o1, n]明显要比[…, n]要长, 所以我们肯定要取前者, 同时我们还要对 o1 往后的元素进行替换。 如果 o < n, 那我们前面的替换对当前的状态是没有影响的。所以无论是哪种情况, 替换掉 lis 中最小的比当前 obstacle 大的元素都不会影响我们后续查找最优解。


impl Solution {
    pub fn longest_obstacle_course_at_each_position(obstacles: Vec<i32>) -> Vec<i32> {
        let mut lis = Vec::new();
        let mut ans = vec![0; obstacles.len()];
        for (i, o) in obstacles.into_iter().enumerate() {
            if let Some(&last) = lis.last() {
                if o >= last {
                    lis.push(o);
                    ans[i] = lis.len() as i32;
                    continue;
                }
                let mut l = 0;
                let mut r = lis.len() - 1;
                while l < r {
                    let m = (l + r) / 2;
                    if lis[m] <= o {
                        l = m + 1;
                        continue;
                    }
                    r = m;
                }
                lis[l] = o;
                ans[i] = l as i32 + 1;
                continue;
            }
            lis.push(o);
            ans[i] = lis.len() as i32;
        }
        ans
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值