文章目录
- [LeetCode:62. 不同路径](#LeetCode:62. 不同路径)
- [LeetCode:63. 不同路径 II](#LeetCode:63. 不同路径 II)
- [LeetCode:343. 整数拆分](#LeetCode:343. 整数拆分)
- [LeetCode:96. 不同的二叉搜索树](#LeetCode:96. 不同的二叉搜索树)
LeetCode:62. 不同路径
https://leetcode.cn/problems/unique-paths/description/
思路
第一行和第一列单独处理。
dp[i][j] = dp[i][j-1] + dp[i-1][j] .
解答
python
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
dp = [[None for _ in range(n)] for _ in range(m)]
dp[0][0] = 1
for i in range(1, m):
dp[i][0] = 1
for j in range(1, n):
dp[0][j] = 1
for i in range(1, m):
for j in range(1, n):
dp[i][j] = dp[i][j-1] + dp[i-1][j]
return dp[m-1][n-1]
LeetCode:63. 不同路径 II
https://leetcode.cn/problems/unique-paths-ii/description/
思路
第一行和第一列单独处理。
如果当前位置没有石头:dp[i][j] = dp[i][j-1] + dp[i-1][j]
如果当前位置有石头:dp[i][j] = 0
解答
python
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
m = len(obstacleGrid)
n = len(obstacleGrid[0])
dp = [[None for _ in range(n)] for _ in range(m)]
row = 0
while row < m: # 处理第一列
if obstacleGrid[row][0] == 0: # 第一列没有遇到石头
dp[row][0] = 1
else: # 遇到石头就退出
break
row += 1
while row < m: # 第一列剩下的都变0
dp[row][0] = 0
row += 1
col = 0
while col < n: # 同理,处理第一行
if obstacleGrid[0][col] == 0:
dp[0][col] = 1
else:
break
col += 1
while col < n:
dp[0][col] = 0
col += 1
# 处理剩下的格子
for i in range(1, m):
for j in range(1, n):
if obstacleGrid[i][j] == 0: # 如果当前位置没有石头
dp[i][j] = dp[i][j-1] + dp[i-1][j]
else: # 如果当前位置有石头
dp[i][j] = 0
return dp[m-1][n-1]
LeetCode:343. 整数拆分
https://leetcode.cn/problems/integer-break/description/
思路
- 对于固定份数 k,乘积最大化的拆分是使各数尽可能相等。
当给定若干个正整数的和固定时,这些数越接近,它们的乘积越大。因此,对于整数拆分,将 n 分成 k 份,最优策略是让各份尽可能平均。 - 乘积随份数 k 的变化先增后减
当 k 较小时,增加份数可以避免出现大的数,乘积会增大;但当 k 过大时,份数中会出现很多 1,乘积反而下降。因此,乘积关于 k 是单峰的,可以提前终止。
解答
python
class Solution:
def integerBreak(self, n: int) -> int:
results = []
for k in range(2, n + 1):
nums = [n // k] * k # 尽可能平均分成k份
remain = n % k # 平均分完后剩余的数字
for i in range(len(nums)): # 将剩余的数字平均分配
if remain > 0:
nums[i] += 1
remain -= 1
else:
break
total = 1
for num in nums:
total *= num
results.append(total)
if len(results) >= 2 and results[-1] < results[-2]: # 如果出现递减,则后续不用再看
break
return max(results)
LeetCode:96. 不同的二叉搜索树
https://leetcode.cn/problems/unique-binary-search-trees/
思路
dp[i] += dp[j - 1] * dp[i - j] ,j - 1 为 j 为头结点左子树节点数量,i - j 为以 j 为头结点右子树节点数量。
解答
python
class Solution:
def numTrees(self, n: int) -> int:
dp = [0] * (n + 1)
dp[0] = 1
for i in range(1, n + 1):
for j in range(1, i + 1):
dp[i] += dp[j - 1] * dp[i - j]
return dp[n]