Leetcode学习计划之动态规划入门day16(64,221)

本文介绍了使用动态规划解决LeetCode中的两道经典问题:64.最小路径和与221.最大正方形。针对每个问题,文章详细解析了算法思路,并提供了Python代码实现。最小路径和问题通过动态规划求解,从左上角到右下角的最小路径和;最大正方形问题同样使用动态规划,找到包含1的最大正方形的边长。
摘要由CSDN通过智能技术生成

目录

64. 最小路径和

问题描述

思路与算法

代码实现

221. 最大正方形

问题描述

思路与算法1:暴力搜索

思路与算法2:动态规划


64. 最小路径和

问题描述

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

示例 1:

输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。

示例 2:

输入:grid = [[1,2,3],[4,5,6]]
输出:12

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 200
  • 0 <= grid[i][j] <= 100

思路与算法

  动态规划。以dp(i,j)表示从格子起点触发到达(i,j)的最小总和路径的路径和。

  由于只能向右或者向下移动,所以有以下递推关系:

  • For i=0, j>0, dp(i,j) = grid[0][j] + dp(0,j-1),因为只能从(0,j-1)到达(0,j)
  • For i>0, j=0, dp(i,j) = grid[i][0] + dp(i-1,0),因为只能从(i-1,0)到达(i,0)
  • For i>0, j>0, dp(i,j) = grid[i][j] + min(dp(i-1,j),dp(i,j-1)),因为可以从两个格点到达(i,j),选择其中总和较小的一个

代码实现

class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])
        dp = [ n*[0] for i in range(m)] 
        
        dp[0][0] = grid[0][0]
        for j in range(1,n):
            dp[0][j] = grid[0][j] + dp[0][j-1]
        for i in range(1,m):
            dp[i][0] = grid[i][0] + dp[i-1][0]
        
        for i in range(1,m):
            for j in range(1,n):
                dp[i][j] = grid[i][j] + min(dp[i-1][j],dp[i][j-1])
        # print(dp)
        return dp[m-1][n-1]

        执行用时:48 ms, 在所有 Python3 提交中击败了70.30%的用户

        内存消耗:16.7 MB, 在所有 Python3 提交中击败了20.34%的用户

221. 最大正方形

问题描述

在一个由 '0' 和 '1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积。

示例 1:

输入:matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出:4

示例 2:

输入:matrix = [["0","1"],["1","0"]]
输出:1

示例 3:

输入:matrix = [["0"]]
输出:0

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 300
  • matrix[i][j] 为 '0' 或 '1'

思路与算法1:暴力搜索

       遍历每个格点。统计以每个格点为左上角的最大正方形面积。

       查询最大正方形面积时,逐层向外扩展。碰到0格点或者越出边界即停止。 

 

class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        m,n = len(matrix),len(matrix[0])
        def get(i,j):
            if i>=m or j>=n:
                return 0
            else:
                return int(matrix[i][j])
            
        maxarea = 0
        for i in range(m):
            for j in range(n):
                # print('.....',i,j)
                if get(i,j) == 0:
                    continue
                else:
                    # Find the max square with (i,j) as the top-left corner
                    area  = 1
                    layer = 1
                    flag  = True
                    while True:
                        for j1 in range(j,j+layer+1):
                            if get(i+layer,j1) ==0:
                                flag = False
                                break
                        if flag is False:
                            break
                        
                        for i1 in range(i,i+layer+1):
                            if get(i1,j+layer)==0:
                                flag = False
                                break
                        if not flag:
                            break
                        # print(i,j,layer,flag)
                        area  += 2*layer + 1
                        layer += 1
                    # print(i,j,layer,area)
                    maxarea = max(maxarea,area)
        return maxarea

        超时。 

思路与算法2:动态规划

        用 \textit{dp}(i, j) 表示以 (i, j) 为右下角,且只包含 1 的正方形的边长最大值。如果我们能计算出所有 \textit{dp}(i, j) 的值,那么其中的最大值即为矩阵中只包含 1 的正方形的边长最大值,其平方即为最大正方形的面积。

        对于每个坐标 (i, j)进行考察:

  • 如果matrxix[i][j]等于0,显然有dp(i,j) = 0
  • 如果i或者j等于0,则dp(i,j)\leq 1
  • 如果matrxix[i][j]等于1,动态转移方程为dp(i,j)=min(dp(i-1,j),dp(i-1,j-1),dp(i,j-1))+1
class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        m,n = len(matrix),len(matrix[0])
        ans = 0
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == "0":
                    matrix[i][j] = 0
                elif (i==0 or j==0):
                    matrix[i][j] = 1
                else:
                    matrix[i][j] = min(matrix[i-1][j],matrix[i][j-1],matrix[i-1][j-1]) + 1
               
                ans = max(ans,matrix[i][j])
        return ans*ans

 

        执行用时:176 ms, 在所有 Python3 提交中击败了60.34%的用户

        内存消耗:22.8 MB, 在所有 Python3 提交中击败了94.69%的用户

         

        回到总目录:笨牛慢耕的Leetcode每日一题总目录(动态更新。。。)

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笨牛慢耕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值