53. Maximum Subarray
求连续子序列的最大和。
DP分析:
1, dp[0] = nums[0]
2, dp[1] = max (nums[0], nums[1])
dp[2] = max (dp[1]+nums[2], nums[2])
由此可推:dp[i] = max( dp[i-1] + nums[i] , nums[i])
维护一个max,取得最大的dp值即可。
此方法在leetcode上顺利通过,但是存在问题:对于nums数组[-1, -2], 正确答案为:dp[0] = -1, dp[1] = -1,而使用上述逻辑,将得到dp[0] = -1, dp[1] = max(-1 + -2 , -2) = -2。
递推式应改为:dp[i] = nums[i] + ( dp[i-1] > 0? dp[i-1] : 0 )
即,当上一状态为负值时,直接抛弃,因为当前值加上负值必定小于当前值。
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.empty())
return 0;
int n = nums.size();
vector<int> f(n);
f[0] = nums[0];
int res = nums[0];
for(int i=1; i<n; i++)
{
//f[i] = max(f[i-1] + nums[i], nums[i]); // some case will be wrong
f[i] = nums[i] + (f[i-1]>0 ? f[i-1] : 0);
res = max(res, f[i]);
}
return res;
}
};
152
.
Maximum Product Subarray
求连续子序列的最大乘积。
成绩问题考虑一点,当前的最大负数,再乘上一个负数就有可能变为最大值。
故维护两个变量: imax 和 imin,分别表示当前步的最大数和最小数。当操作的数值为负数是,将imax和imin对换。结果res在每一步与imax进行比对,若imax大于res则更新res为imax值。
class Solution {
public:
int maxProduct(vector<int>& nums) {
if(nums.empty())
return 0;
int curr = nums[0];
int imax = curr;
int imin = curr;
int res = curr;
for(int i=1; i<nums.size(); i++)
{
if (nums[i] < 0)
swap(imax, imin);
imax = max(nums[i], nums[i] * imax);
imin = min(nums[i], nums[i] * imin);
res = max(res, imax);
}
return res;
}
};
64. Minimum Path Sum
矩形左上到右下的路径和最小值。
首先,对于任一点dp(i, j),其最小和值等于 ①【min(左邻点的最小和值,上邻点的最小和值) + 点本身的值】。
对于第一行与第一列,没有上邻点/左邻点,故其最小和值就等于左邻点/上邻点的最小和值 + 本身的值。
其他点则按关系式①推出即可。
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int rows = grid.size();
int cols = grid[0].size();
vector<vector<int> > dp(rows, vector<int>(cols, grid[0][0]));
// the first col
for (int i = 1; i < rows; i++)
dp[i][0] = dp[i - 1][0] + grid[i][0];
// the first row
for(int j=1; j<cols; j++)
dp[0][j] = dp[0][j-1] + grid[0][j];
for(int i=1; i<rows; i++)
for(int j=1; j<cols; j++)
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j];
return dp[rows-1][cols-1];
}
};
718. Maximum Length of Repeated Subarray
给出两个array,求公共最长子序列。
定义:dp(i, j)表示以以第i个与第j个结尾的公共最长子序列的长度。
关系:若A(i-1) = B(j-1), 则dp(i, j)=dp(i-1, j-1) + 1
因为其实得到的dp(i, j) 表示的是A的第i个和B的第j个,所以算值是A(i-1) = B(j-1),并且循环体中的i与j的范围是1~size。