其他分享
首页 > 其他分享> > 买卖股票的最佳时机 II

买卖股票的最佳时机 II

作者:互联网

给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/x2zsx1/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

下面参考了leetcode大神的题解,进行了解法的整理

方法1:最简单的方法:找到算法规律/最大化贪心

股票可能会买入也可能不买,股票的价格在一段时间内会上升也可能会下降,怎么知道在未来股票的最大价格?然后决定现在是不是应该买入或卖出?
先不想那么多,我们不是要预测未来而是面对一个给定的数组,因此我们始终能给出最优解:明天的价格只要上升,今天就买入,明天的价格只要下降今天就卖出
因此这就是一个上升区间累加的贪心问题,不要被股票给唬住,因为我们能知道明天是什么样总能给出最优解。ps:说了这么多,其实是因为作为一个小白,我的思路一开始就被唬住了。

/**
     * 只要当天价格大于昨天,就可以作差累计收益
     * @param prices
     * @return
     */
    public static int maxProfit(int[] prices) {
        if (prices.length == 1) {
            return 0;
        }
        int res = 0;
        for (int i = 1; i < prices.length; i++) {
            if (prices[i] > prices[i - 1]) {
                res += (prices[i] - prices[i - 1]);
            }
        }
        return res;
    }

方法2:贪心

如果当天只能买入或卖出呢?那就要分区间考虑,找到区间的最小值和最大值进行作差,然后累加到结果

/**
     * 计算区间,寻找区间的最小值和最大值,然后作差累加到结果
     * 在区间内的循环比较时,index始终指向最值,即循环满足条件index++去指向最值
     * 区间结束index++键入下一区间
     *
     * @param prices
     * @return
     */
    public static int maxProfit(int[] prices) {
        int len = prices.length;
        if (len == 1) {
            return 0;
        }
        int index = 0;
        int res = 0;
        while (index < len) {
            while (index < len - 1 && prices[index] > prices[index + 1]) {
                index++; //以上两个条件都满足,说明index不是最后一位,且下一位的值比当前位更小,则index++指向下一位
            }
            int min = prices[index]; //循环结束或不进入循环都说明index指向最小位
            while (index < len - 1 && prices[index] < prices[index + 1]) {
                index++; //以上两个条件都满足,说明index不是最后一位,且下一位的值比当前位更大,则index++指向下一位
            }
            res += prices[index] - min;
            index++;//上述过程找到了一个区间的最大最小值,此时index++进入下一区间
        }
        return res;
    }

方法3:动态规划

在看leetcode题解时看到的动态规划解法。正好可以用这道简单题写写动态规划
如果当前的状态与上一次的状态有关就可以使用动态规划。

/**
     * 动态规划
     * 1.当前一天状态只收前一天状态影响
     * 2.每天交易完由两个状态,持有股票,不持有股票
     * 3.分析两种状态和前一天两种状态的关系
     * 4.考虑初态
     */
    public static int maxProfit(int[] prices) {
        int n = prices.length;
        if(n == 1){
            return 0;
        }
        int res = 0;
        int[][] dp = new int[n][2]; //n对应每天 每天具有两个状态 0为不持有股票 1为持有股票
        //dp数组初态
        dp[0][0] = 0;//第一天不买入
        dp[0][1] = -prices[0];//第一天买入
        for(int 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]);
        }
        res = Math.max(dp[n - 1][0], dp[n - 1][1]);//最后一天结果取最大值;
        return res;
    }

方法4 动态规划优化

/**
     * 动态规划的dp数组是为了记住更早时间的状态
     * 如果当前状态至于前一天的状态有关,那么可以只有状态相同数量的变量存储就可以
     * 也就是说更早的状态无用
     */
    public static int maxProfit(int[] prices) {
        int n = prices.length;
        if(n == 1){
            return 0;
        }
        int res = 0;
        //dp数组初态
        int noHold = 0;//第一天不买入
        int hold = -prices[0];//第一天买入
        for(int i = 1; i < n; i++){
            //今天未持有股票只能是今天没有交易,或前一天就没有持有股票
            int temp = noHold;
            noHold = Math.max(noHold, hold + prices[i]);
            //今天持有股票只能是今天买入,或前一天就持有
            hold = Math.max(hold, temp - prices[i]);
        }
        res = Math.max(noHold, hold);//最后一天结果取最大值;
        return res;
    }

标签:index,买卖,int,res,II,++,最佳时机,prices,dp
来源: https://www.cnblogs.com/zjq-blog/p/15387821.html