目录
问题定义
你打算构建一些障碍赛跑路线。给你一个 下标从 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.length
1 <= n <= 105
1 <= obstacles[i] <= 107
思路
选用的方法是动态规划结合二分查找。动态规划用于维护一个递增序列,而二分查找用于快速定位新障碍物在递增序列中的插入位置。
解题过程
- 初始化两个列表
d
和ans
,其中d
用于存储当前最长递增障碍高度序列,ans
用于存储每个位置的最长障碍赛跑路线长度。 - 遍历输入的障碍物列表
obstacles
。 - 对于每个障碍物
ob
:- 如果
d
为空或者ob
大于或等于d
中最后一个元素,说明它可以作为递增序列的一部分,将其添加到d
的末尾,并更新ans
中当前位置的长度为d
的长度。 - 如果
ob
小于d
的最后一个元素,使用二分查找bisect_right
找到ob
应该插入d
中的位置loc
。这保证了d
仍然是递增的。 - 更新
ans
中当前位置的长度为loc + 1
,这表示当前障碍物之前有loc
个障碍物可以形成递增序列。 - 将
d
中loc
位置的元素更新为ob
,以保持递增序列的特性。
- 如果
- 返回
ans
列表,它包含了每个位置的最长障碍赛跑路线长度。
复杂度
时间复杂度:O(n log n),其中 n 是障碍物列表的长度。这是因为对于每个障碍物,我们最多进行一次二分查找和一次列表插入操作,二分查找的时间复杂度为 O(log n),列表插入操作的时间复杂度为 O(n)。在最坏的情况下,每个障碍物都需要进行这两项操作,因此总的时间复杂度为 O(n log n)。
空间复杂度:O(n),我们需要额外的列表 d
来存储递增序列,其长度在最坏情况下与输入列表 obstacles
的长度相同。同时,ans
列表也与输入列表长度相同。因此,空间复杂度为 O(n)。
code
#会超时
def longestObstacleCourseAtEachPosition(obstacles):
n = len(obstacles)
dp = [1] * n # 初始化dp数组,每个障碍至少包含自身,长度为1
max_height = 0 # 用于记录当前遍历到的障碍中的最大高度
for i in range(1, n):
# 初始化为1,表示至少包含自身
max_height = 1
for j in range(i):
# 如果当前障碍比之前的障碍高或相等,更新最长路线长度
if obstacles[i] >= obstacles[j]:
max_height = max(max_height, dp[j] + 1)
dp[i] = max_height # 更新dp数组
return dp
class Solution:
def longestObstacleCourseAtEachPosition(self, obstacles: List[int]) -> List[int]:
d = list()
ans = list()
for ob in obstacles:
# 这里需要改成 >=
if not d or ob >= d[-1]:
d.append(ob)
ans.append(len(d))
else:
# 如果是最长严格递增子序列,这里是 bisect_left
# 如果是最长递增子序列,这里是 bisect_right
loc = bisect_right(d, ob)
ans.append(loc + 1)
d[loc] = ob
return ans
标签:找出,障碍赛跑,obstacles,ob,为止,路线,ans,长度,障碍
From: https://blog.csdn.net/Sxiaocai/article/details/141333488