常见动态规划问题

115 阅读2分钟

121.买卖股票的最佳时机

链接

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

因为第i天的状态与前i-1天有关,考虑动态规划。 记: 记

prices[i]表示股票在第i天的价格prices[i] 表示股票在第 i 天的价格
dp[i]dp[i]表示在第ii天卖出股票时的最大收益dp[i]dp[i] 表示在第 ii 天卖出股票时的最大收益
dp_min[i]dpmin[i]表示前ii天(包含ii)该股票的最低购入价格dp\_min[i]dp_min[i] 表示前 ii 天(包含 ii )该股票的最低购入价格

可以写出如下代码(Java)

class Solution {
    public int maxProfit(int[] prices){
        int len = prices.length;
        int[] dp_min = new int[len];
        int[] dp = new int[len];
        dp_min[0] = prices[0];
        dp[0] = 0;
        for(int i=1;i<len;i++){           
            // 计算第i天的最大利润
            // 要么在第i天卖出,要么在前i-1天卖出
            dp[i] = Math.max(dp[i-1],prices[i]-dp_min[i-1]);
            // 计算第i天及以前最小价格
            dp_min[i] = Math.min(dp_min[i-1],prices[i]);
        }
        return dp[len-1];
    }
}

我们发现第i天的最小价格与最大收益,都只与第i-1天有关,所以我们可以将O(n)的时间复杂度修改为O(1)。

class Solution {
    public int maxProfit(int[] prices){
        int len = prices.length;
        int pre_min = prices[0];
        int ans = 0;
        for(int i=1;i<len;i++){           
            // 计算第i天的最大利润
            // 要么在第i天卖出,要么在前i-1天卖出
            ans = Math.max(ans,prices[i]-pre_min);
            // 计算第i天及以前最小价格
            pre_min = Math.min(pre_min,prices[i]);
        }
        return ans;
    }
}