Leetcode面试经典150题-123.买卖股票的最佳时机III

解法都在代码里,不懂就留言或者私信

建议看这个之前先看股票系列的其他问题123.买卖股票的最佳时机III

Leetcode面试经典150题-121.买卖股票的最佳时机-CSDN博客

Leetcode面试经典150题-122.买卖股票的最佳时机II-CSDN博客

Leetcode面试经典150题-188.买卖股票的最佳时机IV-CSDN博客

尤其是122和188题,这个题的解题其实就是一个简单的加工

java 复制代码
class Solution {
    public static int maxProfit(int[] prices) {
        return maxProfit(2, prices);
    }

    /**
     * 本题比股票问题2多了一个限制:最多交易k次,也就是可能不能像我们之前的那种每次波谷都买,每次波峰都卖的方式
     * 除非k是大于等于prices.length/2的
     * @param k 这里的k是交易的对数,也就是买一次卖一次
     * @param prices
     * @return
     */
    public static int maxProfit(int k, int[] prices) {
        if(prices == null || prices.length < 2 || k < 1) {
            return 0;
        }
        int ans = 0;
        //如果交易数限制大于prices.length/2,那我们还是可以认为这就是无限次的交易
        //套用股票问题2的解法
        if(k >= prices.length / 2) {
            for(int i = 1; i < prices.length; i++) {
                int curProfit = Math.max(0,prices[i] - prices[i - 1]);
                ans += curProfit;
            }
            return ans;
        } else {
            int N = prices.length;
            //如果小于这个次数的话就需要好好分析一下了,这里我们使用动态规划的从左往右的尝试模型+业务限制进行解题
            //先定义一个动态规划表,表中dp[i][j]代表从0~i做不超过j次交易可以获得的最大的利润,所以i的变化范围0~N-1,j的变化范围从0到k
            int[][] dp = new int[N][k+1];
            //第一行表示从0~0做0~k次交易,都是0,int默认是0,这里忽略初始化
            //第一列表示从0~0,0~1...0~N分别做0次交易,你都没有做交易,你有啥利润,也都是0,同样忽略初始化过程
            //从dp[1][1]开始初始化,如果按照一般的方式进行初始化则dp[8][2] 有几种可能性(1)8位置不交易,那这种可能是dp[7][2]
            //(2)8位置参与交易,那8位置只能卖(因为我们限制0~8进行2次交易,如果你8位置是买的话利润就无法计算到dp[8][2]里了)
            //那我们可以分别在0~8进行买入,分别是dp[8][1] + prices[8] - prices[8](8位置买入,8位置卖出)
            //dp[7][1] + prices[8] - prices[7](7位置买入,8位置卖出)....dp[0][1] + prices[8] - prices[1]
            //也是就说在O(N*k)的基础上我们又加上了枚举行为,时间复杂度变成了O(N^2*k)这个对于leetCode给的数据量来说,不一定能过
            //这里我们尝试进行斜率优化,斜率优化分析过程参考:https://www.xiaohuazhuo.com/board/658accf232120d0c5d74f794
            //这里简单描述一下,其实我们dp[8][2]求解过程中可能性2的每一项都加上了price[8]这个数,也就是说比较过程我们可以不计算这个数
            //在dp[8][1] - [8] dp[7][1] - [7]....dp[0][1] - [0]中取最大值max,然后+[8]就是当前可能性2的最大值
            //为什么要求这样的最大值呢,因为我们之后的计算过程用的上,现在举一个dp[9][2]的求解过程,可能性1:9位置不交易 =dp[8][2]
            //9位置交易,那0~9都可以买入,分别是dp[9][1] + [9] - [9](9位置买入,9位置卖出) dp[8][1] + [9] - [8](8位置买入,9位置卖出)
            // dp[7][1] + prices[9] - prices[7](7位置买入,9位置卖出)....dp[0][1] + prices[9] - prices[1]
            //这些项里我们又看到了加上了一样的prices[9], 所以比较的时候只需要拿dp[9][1] - [9] dp[8][1] - [8] dp[7][1] - [7]....dp[0][1] - [0]
            //这些取最大值就可以了,但是这些出了第一项之外,不就是dp[8][2]的时候求的max吗?所以复用dp[9][2]时候的max=Math.max(max, dp[9][1] - [9])
            //也就是说对于同一列的后面的行只需要多计算一个数(dp[i][j-1] - prices[i]),然后根据前面的max计算就可以了
            for(int j = 1; j <= k; j++) {
                //对于同一列,后面的行依赖于前面的行,这里我们定义一下公共的依赖
                //这里要注意max的初始值不是0,而是dp[0][j] + prices[0]-prices[0] 的中间部分,也就是dp[0][j]-prices[0]
                int max = dp[0][j]-prices[0];
                int p1 = 0;
                for(int i = 1; i < N; i ++) {
                    p1 = dp[i - 1][j];//0
                    //max函数第一个参数就是当前位置要计算的数dp[i][j-1] - prices[i]
                    max = Math.max(dp[i][j - 1] - prices[i], max);//dp[1][0]-dp
                    dp[i][j] = Math.max(p1, max + prices[i]);
                    System.out.println(i+","+ j + "=" + dp[i][j]);
                }
            }
            ans = dp[N-1][k];
        }
        return ans;
    }
}

这个题解法回头我和股票问题4综合一下,其实两个题是一样的,面试肯定保过

相关推荐
tinker在coding10 分钟前
Coding Caprice - Linked-List 1
算法·leetcode
LCG元3 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
XH华5 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生5 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_5 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子5 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
菜鸡中的奋斗鸡→挣扎鸡5 小时前
滑动窗口 + 算法复习
数据结构·算法
Lenyiin6 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码6 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
scan7246 小时前
LILAC采样算法
人工智能·算法·机器学习