DP

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;
    }
};

64Minimum 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。




718. Maximum Length of Re

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值