动态规划(基础版) --- 矩阵

动态规划

基础篇 — 矩阵



一、不同路径

题目

题意

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

代码

方法一:

import math
class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        return math.comb(m+n-2,n-1)

方法二:

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        s = [1] * n
        for i in range(m-1):
            for j in range(1,n):
                s[j] = s[j-1] + s[j]
        return s[-1]

方法三:

import itertools

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        s = [1] * n
        for i in range(m-1):
            s[:] = itertools.accumulate(s)
        return s[-1]

二、最小路径和

题目

题意

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

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

代码

class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        m = len(grid)
        n = len(grid[0])
        s = []
        s[:] = itertools.accumulate(grid[0])
        for i in range(1,m):
            for j in range(n):
                if j == 0:
                    s[j] = s[j] + grid[i][j]
                else:
                    s[j] = min(s[j-1],s[j]) + grid[i][j]
        return s[-1]

三、不同路径 II

题目

题意

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。

代码

方法一:

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

方法二:

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

四、三角形最小路径和

题目

题意

给定一个三角形 triangle ,找出自顶向下的最小路径和。

每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那么下一步可以移动到下一行的下标 i 或 i + 1 。

代码

方法一:(自上而下)

class Solution:
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        n = len(triangle)
        if n == 1:
            return triangle[0][0]
        for i in range(1,n):
            m = len(triangle[i])
            for j in range(m):
                if j == 0:
                    triangle[i][0] += triangle[i-1][0]
                elif j == m-1:
                    triangle[i][-1] += triangle[i-1][-1]
                else:
                    triangle[i][j] += min(triangle[i-1][j],triangle[i-1][j-1])
        return min(triangle[-1])

方法二:(自下而上)

class Solution:
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        n = len(triangle)
        for i in range(n-2,-1,-1):
            for j in range(len(triangle[i])):
                triangle[i][j] += min(triangle[i+1][j],triangle[i+1][j+1])
        return triangle[0][0]

五、下降路径最小和

题目

题意

给你一个 n x n 的 方形 整数数组 matrix ,请你找出并返回通过 matrix 的下降路径 的 最小和 。

下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col) 的下一个元素应当是 (row + 1, col - 1)、(row + 1, col) 或者 (row + 1, col + 1) 。

代码

方法一:

class Solution:
    def minFallingPathSum(self, matrix: List[List[int]]) -> int:
        n = len(matrix)
        for i in range(n-2,-1,-1):
            for j in range(n):
                if j == 0:
                    matrix[i][j] += min(matrix[i+1][j],matrix[i+1][j+1])
                elif j == n-1:
                    matrix[i][j] += min(matrix[i+1][j-1],matrix[i+1][j])
                else:
                    matrix[i][j] += min(matrix[i+1][j-1],matrix[i+1][j],matrix[i+1][j+1])
        return min(matrix[0])

方法二:

class Solution:
    def minFallingPathSum(self, matrix: List[List[int]]) -> float:
        n = len(matrix)
        matrix[0] = [inf] + matrix[0] + [inf]
        for i in range(1,n):
            matrix[i] = [inf] + matrix[i] + [inf]
            for j in range(1,n+1):
                matrix[i][j] += min(matrix[i-1][j-1],matrix[i-1][j],matrix[i-1][j+1])
        return min(matrix[-1])

六、最大正方形

题目

题意

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

代码

方法一:(暴力解法)

class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        s = 0
        n = len(matrix)
        m = len(matrix[0])
        f = False
        for i in range(n):
            for j in range(m):
                if matrix[i][j] == "1":
                    f = True
                while f :
                    if i+s<n and j+s<m:
                        for a in range(i,i+s+1):
                            for b in range(j,j+s+1):
                                if matrix[a][b] == "0":
                                    f = False
                                    break
                            if not f :
                                break
                    else:
                        f = False
                    if f :
                        s += 1
        return s**2

方法二:(动态规划,二维数组)

class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        m,n = len(matrix),len(matrix[0])
        dp = [[0]*n for _ in range(m)]
        s = 0
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == "1":
                    if i == 0 or j == 0:
                        dp[i][j] = 1
                    else:
                        dp[i][j] = min(dp[i-1][j-1],dp[i-1][j],dp[i][j-1]) + 1
                    s = max(s,dp[i][j])

        return s**2

方法三:(动态规划,一维数组)

class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        m,n = len(matrix),len(matrix[0])
        dp = [0]*n
        s = 0
        for i in range(m):
            for j in range(n):
                tmp = dp[j]
                if matrix[i][j] == "1":
                    if j == 0:
                        dp[j] = 1
                    else:
                        dp[j] = min(prev,dp[j-1],dp[j]) + 1
                    s = max(s,dp[j])
                else:
                    dp[j] = 0
                prev = tmp
        return s**2

方法四:(二进制思路)

class Solution:
    def getWeight(self,num):
        c = 0
        while num > 0:
            num &= num<<1
            c += 1
        return c
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        s = [int("".join(i),base = 2) for i in matrix]
        res,n = 0,len(s)
        for i in range(n):
            temp = s[i]
            for j in range(i,n):
                temp &= s[j]
                w = self.getWeight(temp)
                h = j-i+1
                res = max(res,min(w,h))
        return res**2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值