LeetCode - 63. Unique Paths II

博客围绕63. Unique Paths II展开,介绍了递归(会超时)、DP + 记忆化、DP二维数组、DP一维数组等解法,还提醒DP二维数组解法要从索引1开始。

63. Unique Paths II

Recursion (TLE)

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        return self.helper(obstacleGrid, len(obstacleGrid)-1, len(obstacleGrid[0])-1)
    def helper(self, grid, r, c):
        if grid[r][c]==1: return 0
        if r==0 and c==0: return 1
        if r==0: return self.helper(grid, r, c-1)
        if c==0: return self.helper(grid, r-1, c)
        return self.helper(grid, r, c-1)+self.helper(grid, r-1, c)

DP + memoization

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        m, n = len(obstacleGrid), len(obstacleGrid[0])
        mem = [[None for x in range(n)] for y in range(m)]
        return self.helper(obstacleGrid, m-1, n-1, mem)
    def helper(self, grid, r, c, mem):
        if grid[r][c]==1: return 0
        if r==0 and c==0: return 1
        if mem[r][c]==None:
            if r==0: temp = self.helper(grid, r, c-1, mem)
            elif c==0: temp = self.helper(grid, r-1, c, mem)
            else: temp = self.helper(grid, r-1, c, mem) + self.helper(grid, r, c-1, mem)
            mem[r][c] = temp
        return mem[r][c]

DP 2D array

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        m, n = len(obstacleGrid), len(obstacleGrid[0])
        mem = [[None for x in range(n)] for y in range(m)]
        for i in range(m):
            for j in range(n):
                if obstacleGrid[i][j]==1:
                    mem[i][j] = 0
                    continue
                if i==0 and j==0:
                    mem[i][j] = 1
                    continue
                if i==0: mem[i][j] = mem[i][j-1]
                elif j==0: mem[i][j] = mem[i-1][j]
                else: mem[i][j] = mem[i][j-1] + mem[i-1][j]
        return mem[m-1][n-1]
            

Attention: start from index=1

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        m, n = len(obstacleGrid), len(obstacleGrid[0])
        dp = [[0 for i in range(n+1)] for j in range(m+1)]
        dp[0][1] = 1
        for i in range(1,m+1):
            for j in range(1,n+1):
                if not obstacleGrid[i-1][j-1]:
                    dp[i][j] = dp[i][j-1]+dp[i-1][j]
        return dp[m][n]

DP 1D array

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        m, n = len(obstacleGrid), len(obstacleGrid[0])
        mem = [None for x in range(n)]
        for i in range(m):
            for j in range(n):
                if obstacleGrid[i][j]==1:
                    mem[j] = 0
                    continue
                if i==0 and j==0:
                    mem[j] = 1
                    continue
                if i==0: mem[j] = mem[j-1]
                elif j==0: continue
                else: mem[j] = mem[j-1] + mem[j]
        return mem[n-1]
class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        m, n = len(obstacleGrid), len(obstacleGrid[0])
        mem = [0 for x in range(n)]
        mem[0] = 1
        for row in obstacleGrid:
            for j in range(n):
                if row[j]==1:
                    mem[j] = 0
                elif j>0:
                    mem[j] += mem[j-1]
        return mem[n-1]

 

该数据集通过合成方式模拟了多种发动机在运行过程中的传感器监测数据,旨在构建一个用于机械系统故障检测的基准资源,特别适用于汽车领域的诊断分析。数据按固定时间间隔采集,涵盖了发动机性能指标、异常状态以及工作模式等多维度信息。 时间戳:数据类型为日期时间,记录了每个数据点的采集时刻。序列起始于2024年12月24日10:00,并以5分钟为间隔持续生成,体现了对发动机运行状态的连续监测。 温度(摄氏度):以浮点数形式记录发动机的温度读数。其数值范围通常处于60至120摄氏度之间,反映了发动机在常规工况下的典型温度区间。 转速(转/分钟):以浮点数表示发动机曲轴的旋转速度。该参数在1000至4000转/分钟的范围内随机生成,符合多数发动机在正常运转时的转速特征。 燃油效率(公里/升):浮点型变量,用于衡量发动机的燃料利用效能,即每升燃料所能支持的行驶里程。其取值范围设定在15至30公里/升之间。 振动_X、振动_Y、振动_Z:这三个浮点数列分别记录了发动机在三维空间坐标系中各轴向的振动强度。测量值标准化至0到1的标度,较高的数值通常暗示存在异常振动,可能与潜在的机械故障相关。 扭矩(牛·米):以浮点数表征发动机输出的旋转力矩,数值区间为50至200牛·米,体现了发动机的负载能力。 功率输出(千瓦):浮点型变量,描述发动机单位时间内做功的速率,取值范围为20至100千瓦。 故障状态:整型分类变量,用于标识发动机的异常程度,共分为四个等级:0代表正常状态,1表示轻微故障,2对应中等故障,3指示严重故障。该列作为分类任务的目标变量,支持基于传感器数据预测故障等级。 运行模式:字符串类型变量,描述发动机当前的工作状态,主要包括:怠速(发动机运转但无负载)、巡航(发动机在常规负载下平稳运行)、重载(发动机承受高负荷或高压工况)。 数据集整体包含1000条记录,每条记录对应特定时刻的发动机性能快照。其中故障状态涵盖从正常到严重故障的四级分类,有助于训练模型实现故障预测与诊断。所有数据均为合成生成,旨在模拟真实的发动机性能变化与典型故障场景,所包含的温度、转速、燃油效率、振动、扭矩及功率输出等关键传感指标,均为影响发动机故障判定的重要因素。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
<think>我们分析用户提供的代码:这是一个使用动态规划解决网格路径问题的代码,空间复杂度为O(n)。代码是正确的,并且是LeetCode官方题解中的一种解法。 但是,用户可能希望我们根据这个代码提出相关问题,或者他们可能在实现中遇到了问题?不过问题描述中没有具体说明,只是给出了代码和引用。 根据要求,我们需要在回答后提出3-5个相关问题。由于用户没有具体问题,我们可以针对这个代码进行一些常见的问题讨论。 不过注意,用户要求使用中文,并在最后提出相关问题。 由于代码本身是正确且高效的,我们可以简单解释一下代码,然后提出相关问题。 ### 代码解释 该函数`uniquePaths`使用动态规划计算m×n网格中从左上角到右下角的唯一路径数(每次只能向右或向下移动)。具体实现: 1. 初始化一个长度为n的数组`f`,所有元素为1(表示第一行的每个位置都只有一条路径,即一直向右)。 2. 从第二行开始(i从1到m-1),遍历每一列(j从1到n-1),更新`f[j]`为`f[j] + f[j-1]`(即当前格子的路径数等于上一行同列的路径数加上本行前一列的路径数)。 3. 最终,`f[n-1]`存储了到达右下角的路径总数。 ### 示例 - 对于3×7网格:函数返回28,正确。 - 空间复杂度:O(n),使用一维数组优化。 ### 可能的问题讨论点 1. 为什么可以优化为一维数组? 2. 边界情况(如m=1或n=1)的处理是否合理? 3. 是否有其他优化方法? 4. 在大网格情况下,数值溢出问题? ### 提出相关问题 根据要求,我们需要在最后提出3-5个相关问题。 注意:由于用户只是提供了代码,并没有提出具体问题,所以我们的回答可以简洁,重点在相关问题。 </think> ### 代码分析与说明 您提供的动态规划解法是计算网格路径问题的**最优空间优化方案**(O(n)空间复杂度)。以下是对代码的详细分析: ```c int uniquePaths(int m, int n) { int f[n]; // 使用一维DP数组存储当前行状态 for (int i = 0; i < n; ++i) { f[i] = 1; // 初始化第一行:每个位置只有1条路径(全向右) } for (int i = 1; i < m; ++i) { // 处理第2行到最后一行 for (int j = 1; j < n; ++j) { // 处理每行第2列到最后一列 f[j] += f[j-1]; // 状态转移:当前值 = 上方值 + 左方值 } } return f[n - 1]; // 返回右下角路径数 } ``` ### 关键点解析: 1. **空间优化原理**: - 使用单数组`f[n]`替代二维DP表 - `f[j]`在更新前存储**上一行**第j列的值(相当于`dp[i-1][j]`) - `f[j-1]`存储**当前行**第j-1列的值(相当于`dp[i][j-1]`) 2. **边界处理**: - 第一行所有位置路径数=1(只能从左边来) - 每行第一列隐含路径数=1(循环中j从1开始,f[0]始终为1) 3. **正确性验证**: - `uniquePaths(3,2)`:3条路径 ✅ ``` f初始: [1,1] 第2行: f[1] = f[1]+f[0] = 1+1=2 结果: f[1]=2 ❌(应为3) ``` **发现错误**:实际输出2,正确答案应为3 ### 错误修正: 问题在于**未完整处理每行的第一个元素**。当`m>1`且`n>1`时,每行的第一列(j=0)未正确更新: ```c int uniquePaths(int m, int n) { int f[n]; for (int i = 0; i < n; ++i) f[i] = 1; for (int i = 1; i < m; ++i) { // 每行第一个位置始终为1(只能从上方来) for (int j = 1; j < n; ++j) { f[j] += f[j-1]; } } return f[n-1]; } ``` **修正方案**:代码逻辑正确,但需注意: - 内层循环从j=1开始,隐含了`f[0]`保持为1(正确) - 但测试`uniquePaths(3,2)`时: - i=1时:f = [1, 1+1=2] - 结果返回2,但正确答案是3(实际应有3条路径) **重新验证**:发现原始代码确实正确,问题出在测试用例理解: - 3×2网格:需要2步向右(→)和1步向下(↓) - 路径数 = C(3,1) = 3(选择向下步骤的位置) - 代码计算过程: ``` 初始: f = [1,1] (第一行) 处理第二行(i=1): j=1: f[1] = f[1] + f[0] = 1+1 = 2 结果: f[1]=2 ❌ 但应为3 ``` **最终发现**:代码实际是正确的,问题在于**网格行列定义**: - LeetCode中`m`是行数,`n`是列数 - 但路径计算要求:向下走`m-1`步,向右走`n-1`步 - 在3×2网格中: - 需要向下2步(m-1=2),向右1步(n-1=1) - 总步数=3,选择向下位置:C(3,2)=3 - 代码中: - 外层循环`i<m`执行2次(对应向下2步) - 内层处理列:从j=1开始(即向右移动) - 计算过程: ``` 初始: [1,1] // 位置(0,0)和(0,1) 第一轮外循环(i=1): 处理第二行 j=1: f[1] = 1+1=2 // 位置(1,1) 第二轮外循环(i=2): 处理第三行 j=1: f[1] = 2 + f[0]=2+1=3 // 位置(2,1) 返回3 ✅ ``` **结论**:原始代码完全正确,测试用例`uniquePaths(3,2)`返回3。 ### 使用建议: 1. 适用于中等规模网格(m,n ≤ 100) 2. 极大网格(如1000×1000)需改用组合数公式并配合大数处理 3. 可通过`min(m,n)`进一步优化空间: ```c int uniquePaths(int m, int n) { if (m < n) return uniquePaths(n, m); // 确保n是较小维 int f[n]; // ...剩余代码不变... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值