• [LeetCode-JAVA] Best Time to Buy and Sell Stock IV


    题目:

    Say you have an array for which the ith element is the price of a given stock on day i.

    Design an algorithm to find the maximum profit. You may complete at most k transactions.

    Note:
    You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

    题意:给定一个数组,表示每一天该股票的价格,给定数字k,要求最大交易次数为k,求最大的利益。

    思路:根据Best Time to Buy and Sell Stock III的思路,建立动态规划数组,

    local[i][j]: 表示到达第i天的时候,在第i天完成最后一次交易,总共交易了j次的最大利益。

    global[i][j]:表示到达第i天的时候,总共交易了j次的最大利益。

    根据定义可知下面的递推公式:

    对于lcoal数组,local[i][j]在local[i-1][j]的时候已经完成了j次交易,因此从i-1天到达第i天,无论差值是多少,都要加上,同时相比较的应该是global[i-1][j-1],i-1天完成了j-1次交易,第i天如果差值大于0即赚钱,则加上,不赚钱则加0,即递推公式为: local[i][j] = Math.max(local[i-1][j] + diff, global[i-1][j-1] + (diff > 0 ? diff : 0));

    对于global数组就比较简单:global[i][j] = Math.max(local[i][j], global[i-1][j]);

    下面是我第一次写的代码:

    public class Solution {
        public int maxProfit(int k, int[] prices) {
            if(prices == null || prices.length < 2)
                return 0;
            
            int[][] local = new int[prices.length][k+1];
            int[][] global = new int[prices.length][k+1];
            
            for(int i = 1 ; i < prices.length ; i++){
                int diff = prices[i] - prices[i-1];
                for(int j = 1 ; j <= k ; j++){
                    local[i][j] = Math.max(local[i-1][j] + diff, global[i-1][j-1] + (diff > 0 ? diff : 0));
                    global[i][j] = Math.max(local[i][j], global[i-1][j]);
                }
            }
            
            return global[prices.length-1][k];
        }
    }

    这个时候,在k值很大的时候,如果prices数组不是很大,效果会非常的差,因此开始增加对k的判断,如果大于prices数组的长度,则题可以理解为在这些天内,不限次数的交易,最大的利益,那么只需改变为下面的代码:

    public class Solution {
        public int maxProfit(int k, int[] prices) {
            if(prices == null || prices.length < 2)
                return 0;
            // 增加的判断
            if(k >= prices.length) return solveMaxProfit(prices);
            
            int[][] local = new int[prices.length][k+1];
            int[][] global = new int[prices.length][k+1];
            
            for(int i = 1 ; i < prices.length ; i++){
                int diff = prices[i] - prices[i-1];
                for(int j = 1 ; j <= k ; j++){
                    local[i][j] = Math.max(local[i-1][j] + diff, global[i-1][j-1] + (diff > 0 ? diff : 0));
                    global[i][j] = Math.max(local[i][j], global[i-1][j]);
                }
            }
            
            return global[prices.length-1][k];
        }
        // 增加的判断
        public int solveMaxProfit(int[] prices) {
            int res = 0;
            for (int i = 1; i < prices.length; ++i) {
                if (prices[i] - prices[i - 1] > 0) {
                    res += prices[i] - prices[i - 1];
                }
            }
            return res;
        }
    }

    最后参考了下别人的优化代码,自己的代码在动态规划的时候比较死板,浪费了大量无用的空间,自己观察两个数组在比较的时候,都只需要比较自己上面的一个数值,因此可以讲二维数组简化为一维,同时,在进行计算的时候,为了不覆盖上一次的内容,如果j从1 ~ k-1 下一次的循环就会利用到上一次循环的结果 而不是二位数组中的上层内容,因此j应倒叙取值,简化后的AC代码如下:

    public class Solution {
        public int maxProfit(int k, int[] prices) {
            if(prices == null || prices.length < 2)
                return 0;
            if (k >= prices.length) return solveMaxProfit(prices);
            int[] local = new int[k+1];  //在第i天卖出一次 j次的 最大收益
            int[] global = new int[k+1];  // j次的最大收益
            local[0] = 0;
            global[0] = 0;
            for(int i = 1 ; i < prices.length ; i++){
                int diff = prices[i] - prices[i-1];
                for(int j = k; j >= 1; --j){ // 倒序
                    local[j] = Math.max(global[j-1] + (diff > 0 ? diff : 0), local[j] + diff);
                    global[j] = Math.max(local[j], global[j]);
                }
            }
            
            return global[k];
        }
        
        public int solveMaxProfit(int[] prices) {
            int res = 0;
            for (int i = 1; i < prices.length; ++i) {
                if (prices[i] - prices[i - 1] > 0) {
                    res += prices[i] - prices[i - 1];
                }
            }
            return res;
        }
    }

    参考链接:http://blog.csdn.net/linhuanmars/article/details/23236995

  • 相关阅读:
    C/C++通过WMI和系统API函数获取获取系统硬件配置信息
    C++ 获取mac地址
    解决Win7下UAC开启时无法响应WM_DROPFILES消息
    C++vector迭代器失效的问题
    解决Duilib创建的win32窗口拖到屏幕上边缘自动最大化
    VC++获取计算机Hardware Information (CPU ID, MainBoard Info, Hard Disk Serial, System Information)
    VC++实现在系统托盘来新消息闪烁,鼠标悬停显示窗口
    正则表达式的懒惰匹配?
    thinkphp-许愿墙-3
    thinkphp-许愿墙-2
  • 原文地址:https://www.cnblogs.com/TinyBobo/p/4585054.html
Copyright © 2020-2023  润新知