文章目录
前言
动态规划是编程面试中的热门话题,如果面试题是求解一个问题的最优解(通常是求最大值或者最小值),而且该问题能够分解成若干个子问题,并且子问题之间还有重叠的更小的子问题,就可以考虑用动态规划的方法来求解这个问题。
关键名词:
(1) 无后效性:即“未来与过去无关”。(严格定义:如果给定某一阶段的状态,则在这一阶段以后过程的发展不受这阶段以前各段状态的影响。)
(2) 最优子结构性质:即大问题的最优解可以由小问题的最优解推出。
如何判断一个问题能否使用DP解决:能将大问题拆成几个小问题,且满足无后效性、最优子结构性质。
DP的核心思想:尽量缩小可能解空间。
算法题
1. LeetCode 64 : 最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
/*
* 1
* LeetCode 64 : 最小路径和
* https://leetcode-cn.com/problems/minimum-path-sum/
*/
int minPathSum(vector<vector<int>>& grid)
{
int m = grid.size();
int n = grid[0].size();
vector<vector<int> > dp(m,vector<int>(n,0));
dp[0][0] = grid[0][0];
for(int i = 1; i < m; i++)
dp[i][0] = dp[i-1][0] + grid[i][0];
for(int j = 1; j < n; j++)
dp[0][j] = dp[0][j-1] + grid[0][j];
for(int i = 1; i < m; i++)
for(int j = 1; j < n; j++)
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j];
return dp[m-1][n-1];
}
2. LeetCode 53 : 最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
/*
* 2
* LeetCode 53 : 最大子序和
* https://leetcode-cn.com/problems/maximum-subarray/
*/
int maxSubArray(vector<int> &nums)
{
#if 0
//dp[i]表示nums中以nums[i]结尾的最大子序和
if(nums.empty())
{
return -1;
}
vector<int> dp(nums.size());
dp[0] = nums[0];
int res = nums[0];
for (int i = 1; i < nums.size(); i++)
{
dp[i] = max(dp[i - 1] + nums[i], nums[i]);
res = max(res, dp[i]);
}
return res;
#endif
#if 1
// 因为dp[i]只与dp[i-1]有关,所以可以只用只用一个变量 pre 来维护对于当前dp[i]的dp[i-1]的值是多少
if

本文精选了8道典型的动态规划算法题,包括最小路径和、最大子序和等,通过实例详细解析动态规划的核心思想和应用技巧。
最低0.47元/天 解锁文章
3492

被折叠的 条评论
为什么被折叠?



