[算法]数组:买卖股票的最佳时机 II

121 阅读3分钟

题目:

leetcode链接:初级算法-买卖股票的最佳时机 II

说明:给你一个整数数组 prices ,其中 prices[i] 表示某支股票第i天的价格。

在每一天,你可以决定是否购买或出售股票。你在任何时候最多只能持有一股股票。你也可以先购买,然后在 同一天 出售。

返回你能获得的最大利润 。

理解:

1、prices为某股票每日股价的数组:虽然没提,但股票基本仅在工作日会有波动,虽然没什么用,但长度可以锁定为5。

2、你可以决定是否购买或出售股票:在股票数组长度反应的时间内,你可以不买,多次买入或卖出,即每日结束后手里可能有股票或者没股票。

3、你在任何时候最多只能持有一股股票:每日结束后顶多持有一只股票,即持有骨片数量为0或1。

4、你能获得的最大利润:利润为正值,根据股价,如果操作股票会出现负利润,可以不操作,此时顶多没有收益。

大致思路:

1、统计每日有股票和没股票时的收益,在最后一天持有股票的收益将小于不持有股票的收益 - 动态规划

2、统计每日可能的正向股票收益 - 贪心算法

题解:

方案一:动态规划(一)

var maxProfit = function(prices) {
    const n = prices.length;
    const dp = new Array(n).fill(0).map(v => new Array(2).fill(0));
    dp[0][0] = 0, dp[0][1] = -prices[0];
    for (let i = 1; i < n; ++i) {
        dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
        dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
    }
    return dp[n - 1][0];
};

时间复杂度:O(n),其中 nnn 为数组的长度。一共有 2n2n2n 个状态,每次状态转移的时间复杂度为 O(1),因此时间复杂度为 O(2n)=O(n)。

空间复杂度:O(n)。我们需要开辟 O(n) 空间存储动态规划中的所有状态。如果使用空间优化,空间复杂度可以优化至 O(1)。

方案二:动态规划(二)

上面的状态转移方程中,每一天的状态只与前一天的状态有关,而与更早的状态都无关,因此我们不必存储这些无关的状态,只需要将 dp[i−1][0]和 dp[i−1][1]存放在两个变量中,通过它们计算出 dp[i][0]和 dp[i][1]并存回对应的变量,以便于第 i+1天的状态转移即可

var maxProfit = function(prices) {
    const n = prices.length;
    let dp0 = 0, dp1 = -prices[0];
    for (let i = 1; i < n; ++i) {
        let newDp0 = Math.max(dp0, dp1 + prices[i]);
        let newDp1 = Math.max(dp1, dp0 - prices[i]);
        dp0 = newDp0;
        dp1 = newDp1;
    }
    return dp0;
};

方案三:贪心算法

var maxProfit = function(prices) {
    let ans = 0;
    let n = prices.length;
    for (let i = 1; i < n; ++i) {
        ans += Math.max(0, prices[i] - prices[i - 1]);
    }
    return ans;
};

时间复杂度:O(n)O(n)O(n),其中 nnn 为数组的长度。我们只需要遍历一次数组即可。

空间复杂度:O(1)O(1)O(1)。只需要常数空间存放若干变量。

总结:

本篇主要记录了下leetcode"买卖股票的最佳时机"算法题,采用动态规划和贪心算法下的实现,实际或许还有更多更优的解题方案,若时间允许我们可以多做尝试~