LeetCode 题解工作台
找出到每个位置为止最长的有效障碍赛跑路线
你打算构建一些障碍赛跑路线。给你一个 下标从 0 开始 的整数数组 obstacles ,数组长度为 n ,其中 obstacles[i] 表示第 i 个障碍的高度。 对于每个介于 0 和 n - 1 之间(包含 0 和 n - 1 )的下标 i ,在满足下述条件的前提下,请你找出 obstacle…
3
题型
5
代码语言
3
相关题
当前训练重点
困难 · 二分·搜索·答案·空间
答案摘要
我们可以用树状数组维护一个最长递增子序列的长度数组。 然后对于每个障碍,我们在树状数组中查询小于等于当前障碍的最长递增子序列的长度,假设为 ,那么当前障碍的最长递增子序列的长度为 ,我们将 添加到答案数组中,并将 更新到树状数组。
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 二分·搜索·答案·空间 题型思路
题目描述
你打算构建一些障碍赛跑路线。给你一个 下标从 0 开始 的整数数组 obstacles ,数组长度为 n ,其中 obstacles[i] 表示第 i 个障碍的高度。
对于每个介于 0 和 n - 1 之间(包含 0 和 n - 1)的下标 i ,在满足下述条件的前提下,请你找出 obstacles 能构成的最长障碍路线的长度:
- 你可以选择下标介于
0到i之间(包含0和i)的任意个障碍。 - 在这条路线中,必须包含第
i个障碍。 - 你必须按障碍在
obstacles中的 出现顺序 布置这些障碍。 - 除第一个障碍外,路线中每个障碍的高度都必须和前一个障碍 相同 或者 更高 。
返回长度为 n 的答案数组 ans ,其中 ans[i] 是上面所述的下标 i 对应的最长障碍赛跑路线的长度。
示例 1:
输入:obstacles = [1,2,3,2] 输出:[1,2,3,3] 解释:每个位置的最长有效障碍路线是: - i = 0: [1], [1] 长度为 1 - i = 1: [1,2], [1,2] 长度为 2 - i = 2: [1,2,3], [1,2,3] 长度为 3 - i = 3: [1,2,3,2], [1,2,2] 长度为 3
示例 2:
输入:obstacles = [2,2,1] 输出:[1,2,1] 解释:每个位置的最长有效障碍路线是: - i = 0: [2], [2] 长度为 1 - i = 1: [2,2], [2,2] 长度为 2 - i = 2: [2,2,1], [1] 长度为 1
示例 3:
输入:obstacles = [3,1,5,6,4,2] 输出:[1,1,2,3,2,2] 解释:每个位置的最长有效障碍路线是: - i = 0: [3], [3] 长度为 1 - i = 1: [3,1], [1] 长度为 1 - i = 2: [3,1,5], [3,5] 长度为 2, [1,5] 也是有效的障碍赛跑路线 - i = 3: [3,1,5,6], [3,5,6] 长度为 3, [1,5,6] 也是有效的障碍赛跑路线 - i = 4: [3,1,5,6,4], [3,4] 长度为 2, [1,4] 也是有效的障碍赛跑路线 - i = 5: [3,1,5,6,4,2], [1,2] 长度为 2
提示:
n == obstacles.length1 <= n <= 1051 <= obstacles[i] <= 107
解题思路
方法一:树状数组
我们可以用树状数组维护一个最长递增子序列的长度数组。
然后对于每个障碍,我们在树状数组中查询小于等于当前障碍的最长递增子序列的长度,假设为 ,那么当前障碍的最长递增子序列的长度为 ,我们将 添加到答案数组中,并将 更新到树状数组。
时间复杂度 ,空间复杂度 。其中 为障碍的数量。
class BinaryIndexedTree:
__slots__ = ["n", "c"]
def __init__(self, n: int):
self.n = n
self.c = [0] * (n + 1)
def update(self, x: int, v: int):
while x <= self.n:
self.c[x] = max(self.c[x], v)
x += x & -x
def query(self, x: int) -> int:
s = 0
while x:
s = max(s, self.c[x])
x -= x & -x
return s
class Solution:
def longestObstacleCourseAtEachPosition(self, obstacles: List[int]) -> List[int]:
nums = sorted(set(obstacles))
n = len(nums)
tree = BinaryIndexedTree(n)
ans = []
for x in obstacles:
i = bisect_left(nums, x) + 1
ans.append(tree.query(i) + 1)
tree.update(i, ans[-1])
return ans
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | complexity is O(n log n) if using binary search for each obstacle to find its place in the tracking array. Space complexity is O(n) to store the tracking array and the result ans. |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Look for a binary search solution to handle large input sizes efficiently.
- question_mark
Consider how to maintain minimum heights per course length to extend sequences correctly.
- question_mark
Watch for edge cases where obstacles decrease or repeat, impacting sequence length.
常见陷阱
外企场景- error
Failing to maintain the minimum height for each course length can produce shorter sequences than possible.
- error
Using linear scan instead of binary search leads to TLE on large inputs.
- error
Incorrectly updating the tracking array can overwrite valid sequences and reduce the final answer.
进阶变体
外企场景- arrow_right_alt
Find the longest strictly increasing obstacle course at each position.
- arrow_right_alt
Compute the total number of distinct valid obstacle courses ending at each index.
- arrow_right_alt
Determine the maximum obstacle course length if only adjacent elements can be used.