Commit f37791bc authored by anqiwa's avatar anqiwa 😲
Browse files

add dp section

parent 65a15124
/*
* @lc app=leetcode id=152 lang=cpp
*
* [152] Maximum Product Subarray
*/
// @lc code=start
class Solution
{
public:
int maxProduct(vector<int> &nums)
{
const int n = nums.size();
vector<int> maxP(n);
vector<int> minP(n);
maxP[0] = nums[0];
minP[0] = nums[0];
int res = maxP[0];
for (int i = 1; i < n; ++i)
{
maxP[i] = max(max(maxP[i - 1] * nums[i], minP[i - 1] * nums[i]), nums[i]);
minP[i] = min(min(maxP[i - 1] * nums[i], minP[i - 1] * nums[i]), nums[i]);
res = max(res, maxP[i]);
}
return res;
}
};
// @lc code=end
# 152. Maximum Product Subarray
此题是 lc53 的变形,但是是product 而非 sum。 所以这里nums[i] 的符号就很关键了。
### 核心思想:
我们定义:
```cpp
// dp[i] <- 以i为结尾的 max subarray product
const int n = nums.size();
vector<int> maxP(n);
```
1 . 如果 nums[i] 是个非负数,则 maxP = max(nums[i] * maxP[i], nums[i]); 这个和 lc53 是很类似的
2 . 如果 nums[i] 是个负数怎么办?这是此题的难点! 作为一个负数, 其实要找到的是以 i-1 为结尾的 min subarray product, 再与之相乘!
举个栗子,
```
nums [1, -1, -2]
0 1 2
```
那当我们设置有边界 i = 2 时:
- i-1 的 max subarray product 是 1
- i-1 的 min subarray product 是 -1
此时, i 结尾的max subarray product 则为 -2 * -1 = 2
所以,这种情况下, maxP = max(nums[i] * min subarray product(i), nums[i]); 那min subarray product怎么找呢? 我们需要维护另一个dp 记录!
```cpp
vector<int> minP(n);
```
综上,此题的状态转移方程是:
```cpp
maxP[i] = max(max(maxP[i - 1] * nums[i], minP[i - 1] * nums[i]), nums[i]);
```
且每一步都需要更新:
```cpp
minP[i] = min(min(maxP[i - 1] * nums[i], minP[i - 1] * nums[i]), nums[i]);
```
以上就是此题的核心,还是很难的,需要细细品味一下!
\ No newline at end of file
/*
* @lc app=leetcode id=53 lang=cpp
*
* [53] Maximum Subarray
*/
// @lc code=start
class Solution
{
public:
int maxSubArray(vector<int> &nums)
{
// kadane's algo
int res = nums[0];
const int n = nums.size();
vector<int> dp(n);
dp[0] = nums[0];
for (int i = 1; i < n; ++i)
{
dp[i] = max(dp[i - 1] + nums[i],
nums[i]);
res = max(res, dp[i]);
}
return res;
}
};
// @lc code=end
# 53.Maximum Subarray
尽管这题lc上标注的是easy,但是对于第一次见到此题的小伙伴而言,自己想出来还是很困难的。此题的算法是 ```Kadane's Algorithm```
### Kadane's algorithm
核心思想是“固定有边界,探索左边界”。也就是说, 我们考虑每个以i结尾的max subarry 子问题。
所以我们定义:
```cpp
// dp[i] <- 以i为结尾的 max subarray
const int n = nums.size();
vector<int> dp(n);
```
而此题的 result 就是遍历所有dp中可能的i:
```py
//伪代码
res = max{dp[i]}, where i = 1,2,3 ... ,n-1
```
现在我要讨论的是他的状态转移方程,也是此题的难点。有两种情况:
1 . dp[i-1] 为正,则 nums[i] 可以直接与 dp[i-1] 求和,得到max subarray sum
2 . dp[i-1] 为负数,则 这种情况,前面的subarray反而是累赘,max subarray sum直接是 nums[i]
dp[i] 是上面两种情况中取最大的
```cpp
dp[i] = max(dp[i-1] + nums[i], nums[i]);
```
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment