DAY 36 动态规划part02
1. 62.不同路径
一个机器人位于一个 m x n
网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
示例 1:
输入:m = 3, n = 7
输出:28
示例 2:
输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下
代码实现
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
# dp[i][j] i, j索引对应位置的不同路径数
# dp[i][j] = dp[i-1][j] + dp[i][j-1]
# 初始化dp[1][1] = 1
# dp[0][i] , dp[i][0] = 0
# dp = [[0] * (n + 1) for i in range(m + 1)]
# dp[1][1] = 1
# for i in range(1, m + 1):
# for j in range(1, n + 1):
# if i == 1 and j == 1:
# continue
# dp[i][j] = dp[i-1][j] + dp[i][j-1]
# 可以优化空间,一行就行了
dp = [1] * n
for i in range(1, m):
for j in range(1, n):
dp[j] += dp[j-1]
return dp[-1]
2. 62.不同路径II
一个机器人位于一个 m x n
网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1
和 0
来表示。
示例 1:
输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右
代码实现
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
# 同样的 只不过有障碍的对应为 0
m , n = len(obstacleGrid), len(obstacleGrid[0])
# dp = [[0] * (n + 1) for i in range(m + 1)]
# for i in range(1, m + 1):
# for j in range(1, n + 1):
# if i == 1 and j == 1:
# if not obstacleGrid[0][0]:
# dp[1][1] = 1
# continue
# if obstacleGrid[i-1][j-1]:
# dp[i][j] = 0
# else:
# dp[i][j] = dp[i-1][j] + dp[i][j-1]
# return dp[-1][-1]
# 同样
dp = [0] * n
dp[0] = 1 - obstacleGrid[0][0]
for i in range(m):
for j in range(0, n):
if i == 0 and j == 0:
continue
if j == 0:
if obstacleGrid[i][j]:
dp[j] = 0
else:
dp[j] = dp[j] + dp[j - 1] if not obstacleGrid[i][j] else 0
return dp[-1]
3. 343. 整数拆分
给定一个正整数 n
,将其拆分为 k
个 正整数 的和( k >= 2
),并使这些整数的乘积最大化。
返回 你可以获得的最大乘积 。
示例 1:
输入: n = 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。
示例 2:
输入: n = 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
提示:
2 <= n <= 58
思路:
尽量选3,小于5的时候,选剩下的2,3,4
代码实现
class Solution:
def integerBreak(self, n: int) -> int:
# n = 3 --> 3
# n = 2 --> 2
# n = 4 --> 4
# n = 5 --> 2 + 3 -> 6
# 能 3 则 3, 不行则2
if n == 2:
return 1
if n == 3:
return 2
k = 1
while n > 4:
n -= 3
k *= 3
return k * n
4. 96. 不同的二叉搜索树
给你一个整数 n
,求恰由 n
个节点组成且节点值从 1
到 n
互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
示例 1:
输入:n = 3
输出:5
代码实现
class Solution:
def numTrees(self, n: int) -> int:
# 动态规划
# dp[i] 表示i个连续的升数序列能够构成二叉搜索树的大小
# dp[i] = sum([dp[j-1] * dp[i - j] for j in range(1, i + 1)])
dp = [0] * (n + 1)
dp[0] = 1
dp[1] = 1
for i in range(2, n + 1):
dp[i] = sum([dp[j-1] * dp[i - j] for j in range(1, i + 1)])
return dp[-1]