【剑指offer刷题日记】63. 股票的最大利润

152 阅读2分钟

题目

假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?

示例 1:

输入: [7,1,5,3,6,4]

输出: 5

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

示例 2:

输入: [7,6,4,3,1]

输出: 0

解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

解法一 动态规划

只能买卖一次,则我们需要找到前后差值最大的一组数,且前一位比后一位小。那么显而易见,我们在遍历到每个数时,都需要找到他前面最小的数,然后比较差值,看这个差值是不是比我们所拥有的获利大。如果大,则买卖这两个时当前最好的。

运用动态规划的状态转移方程为:dp[i] = max(dp[i-1],prices[i]-min(prices[:i])),这里我们可以再运用一个额外的变量来存储当前最小的prices,即min(prices[:i]),因为我们一直向后在扫描,我们只用比较现在这个prices数和他前面最小的prices的大小,如果小于,则更新最小的prices,大于则依旧沿用前面最小的prices值。

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length == 0) return 0;
        int[] dp = new int[prices.length];
        int curMin = prices[0];
        dp[0] = 0;
        for(int i = 1; i < prices.length;i++){
            // 检查需不需要更新当前最小的prices值
            curMin = Math.min(curMin,prices[i]);
            // 如果现在卖出的钱大于前一天最大的获利,则更新,反之今天的最大获利和昨天一样
            dp[i] = Math.max(dp[i-1], prices[i] - curMin);
        }
        return dp[prices.length-1];
    }
}

时间复杂度:O(n)

空间复杂度: O(n)

解法二 动态规划优化

上一个动态规划,我们运用了一个数组dp来存,但其实我们发现,我们需要的一直只有前一个的最大值,即dp[i-1],所以我们其实用一个变量来代替数组即可,这样可以优化空间。

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length == 0) return 0;
        int result = 0;
        int curMin = prices[0];

        for(int i = 1; i < prices.length;i++){
            curMin = Math.min(curMin,prices[i]);
            result = Math.max(result, prices[i] - curMin);
        }
        return result;
    }
}

时间复杂度:O(n)

空间复杂度: O(1)