首页 > 其他分享 >动态规划:找出每个位置为止最长的有效障碍赛跑路线

动态规划:找出每个位置为止最长的有效障碍赛跑路线

时间:2024-08-19 19:56:31浏览次数:13  
标签:找出 障碍赛跑 obstacles ob 为止 路线 ans 长度 障碍

目录

问题定义

思路

解题过程

复杂度

code


问题定义

        你打算构建一些障碍赛跑路线。给你一个 下标从 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

思路

        选用的方法是动态规划结合二分查找。动态规划用于维护一个递增序列,而二分查找用于快速定位新障碍物在递增序列中的插入位置。


解题过程

  1. 初始化两个列表 d 和 ans,其中 d 用于存储当前最长递增障碍高度序列,ans 用于存储每个位置的最长障碍赛跑路线长度。
  2. 遍历输入的障碍物列表 obstacles
  3. 对于每个障碍物 ob
    • 如果 d 为空或者 ob 大于或等于 d 中最后一个元素,说明它可以作为递增序列的一部分,将其添加到 d 的末尾,并更新 ans 中当前位置的长度为 d 的长度。
    • 如果 ob 小于 d 的最后一个元素,使用二分查找 bisect_right 找到 ob 应该插入 d 中的位置 loc。这保证了 d 仍然是递增的。
    • 更新 ans 中当前位置的长度为 loc + 1,这表示当前障碍物之前有 loc 个障碍物可以形成递增序列。
    • 将 d 中 loc 位置的元素更新为 ob,以保持递增序列的特性。
  4. 返回 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

相关文章

  • 力扣面试经典算法150题:找出字符串中第一个匹配项的下标
    找出字符串中第一个匹配项的下标今天的题目是力扣面试经典150题中的数组的简单题:找出字符串中第一个匹配项的下标题目链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/?envType=study-plan-v2&envId=top-interview-......
  • 使用JMC和socket端口诊断工具找出问题点实例1
    故障上报时间​1月3号下午3点10分原因​应用程序socket使用量累计过多,导致141服务器socket请求数超过linux服务器限制,导致浏览器连接不上。分析过程​先对事故时间段的生产环境域日志、应用日志、应用监控日志进行检查,其中socket属于操作系统管理资源,不在应用监控范......
  • OpenCV图像处理——直线拟合并找出拟合直线的起点与端点
    引言对轮廓进行分析,除了可以对轮廓进行椭圆或者圆的拟合之外,还可以对轮廓点集进行直线拟合。在OpenCV中,直线拟合通常是通过cv::fitLine函数实现的,该函数采用最小二乘法对一组2D或3D点进行直线拟合。对于2D点集,拟合结果是一个cv::Vec4f类型的向量,包含了直线的方......
  • Leetcode-3129 找出所有稳定的二进制数组I
    Leetcode-3129找出所有稳定的二进制数组I1.题目描述2.解题思路3.代码实现1.题目描述3129找出所有稳定的二进制数组I2.解题思路(1)定义f[i][j][k]表示i个0、j个1且当前位i+j填写值为k=0/1的所有情况;(2)对于f[i][0][0]、f[0][j][1]初始化为1,注意到:......
  • Leetcode-3132 找出与数组相加的整数II
    Leetcode-3132找出与数组相加的整数II1.题目描述2.解题思路3.代码实现1.题目描述3132找出与数组相加的整数II2.解题思路(1)排序后,注意到nums1数组比nums2数组多两个元素,可推出最小匹配元素一定在nums[0]、nums[1]、nums[2]中出现;(2)优先从nums[2]进行判......
  • 在两个大文件中找出相同的记录,用golang如何写?
    在两个大文件中找出相同的记录,可以使用Golang实现高效的算法。这里主要涉及以下几个步骤:读取文件:逐行读取两个大文件。使用数据结构存储记录:可以使用Go的map数据结构来存储其中一个文件的记录,之后遍历另一个文件,检查其记录是否在map中,若在则记录下该相同记录。输出结果:将......
  • Python面试宝典第30题:找出第K大元素
    题目        给定一个整数数组nums,请找出数组中第K大的数,保证答案存在。其中,1<=K<=nums数组长度。        示例1:输入:nums=[3,2,1,5,6,4],K=2输出:5        示例2:输入:nums=[50,23,66,18,72],K=3输出:50快速选择算法......
  • (nice!!!)LeetCode 3130. 找出所有稳定的二进制数组 II(动态规划dp)
    题目:3130.找出所有稳定的二进制数组II思路:大佬的思路classSolution{public:intmod=1e9+7;typedeflonglongLL;LLsta[1010][1010][2];//当前还有i个0、j个1时,第i+j的位置放置u,可以组成的合法数目LLdfs(inti,intj,intu,intlimit)......
  • 力扣1.给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值
    1.给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。letnums=[1,2,4,5,3,2,4,6......
  • 找出 python 脚本完成执行所需的时间
    我在python脚本中有以下代码:deffun():#Codeherefun()我想执行此脚本,并找出执行时间(以分钟为单位)。如何查明该脚本的执行时间?一个例子将非常感激。你可以使用time模块来测量Python脚本的执行时间。方法如下:importtimedeffun():#代码写在......