Leetcode Best Time to Buy and Sell Stock系列题目解析以及java实现

Leetcode Best Time to Buy and Sell Stock系列题目解析以及java实现

这一个系列的题目就是让我们在一段连续的股票价格中根据限制来进行交易从而获得最大的利润,每一个衍生题都会设置一些限制

  • Best Time to Buy and Sell Stock I
  • Best Time to Buy and Sell Stock II
  • Best Time to Buy and Sell Stock III
  • Best Time to Buy and Sell Stock with Cooldown
  • Best Time to Buy and Sell Stock with Transaction Fee

Best Time to Buy and Sell Stock I

Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

这一题限制了我们的买卖的次数,所以要要想办法在最低点买入,最高点卖出,但是有一个限制那就是卖出的时间必须在买入之后,所以并不能直接寻找最大值和最小值之差,但是我们可以用一个变量来保存当前扫描过的值的前面的最小值,然后来计算和当前的值的差,如果大于历史最大值则更新最大值

class solution{
	public int maxProfit(int[] prices){
		if(prices == null || prices.length == 0)return 0;
		int minPrice = prices[0];
		int res = 0;
		for(int i = 1; i < prices.length;i++){
			minPrice = Math.min(minPrice,prices[i]);
			res = Math.max(price[i]-minPrice,res);
		}
	}
}

Best Time to Buy and Sell Stock II

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 as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

这一题并不限制买卖的总次数,所以我们就可以采用贪心算法,只要i比i-1天的价格要搞,我们就在i-1天买入,i天卖出获得所有可能的利润。

class Solution{
	public int maxProfit(int[] prices){
		int res = 0;
		for(int i = 1; i < prices.length;i++){
			res += prices[i]-prices[i-1]>0? prices[i]-prices[i-1]:0;
		}
		return res;
	}
}

Best Time to Buy and Sell Stock III

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 two transactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

这一题难度就略有上升了,因为我们只允许买卖两次,而且同时间只能持有一支,也就是说两次交易的区间不可以有重合。于是我们就把这一题分成两个部分
prices[0:n-1] => prices[0:i] + prices[i:n-1]
其中每一段的最大收益就用I中的方法来做,我们先从左往右计算第i日时最大的利润,在从右往左计算一次,最后再相加进行统计,就可以知道以第n天为分割可以获得的最大利润了

class Solution{
	public int maxProfit(int[] prices){
		if(prices == null || prices.length == 0){
			return 0;
		}
		int[] leftProfit = new int[prices.length];
		int leftMin = 0; int leftMaxProfit = 0;
		for(int i = 1; i < prices.length;i ++){
			leftMin = Math.min(leftMin,prices[i];
			leftMaxProfit = Math.max(prices[i]-leftMin,leftMaxProfit);
			leftProfit[i] =  leftMaxProift;
		}
		int[] rightProfit = new int[prices.length];
		int rightMax = prices[prices.length-1],rightMaxProfit = 0;
		int res = 0;
		for(int i = prices.length-2;i >=0;i--){
			rightMax = Math.max(rightMax,prices[i];
			rightMaxProfit = Math.max(rightMax-prices[i],rightMaxProfit);
			rightProfit[i] = rightMaxProfit;
			res = Math.max(res,leftProfit[i]+rightProfit[i]);
		}
		return res;
	}
}

Best Time to Buy and Sell Stock with Cooldown

这一题也是稍微有一些难度的,虽然没有限制我们的买入卖出的次数,但是在卖出之后的第二天时不可以再购入的。

同样我们也是用动态规划来解决这个问题,用两个数组来储存,如果第i日卖或者是第i日不卖的最大利益时多少,然后到最后求两个最大值。
我们同样也是两个数组,如果第i日手里持有,那么只有两种可能,要么我i-1日手里就持有,要么我i日买入了。
如果我i日手里没有持有,要么我i日卖出了,要么我i-1手里就没有持有,但是如果我是i-1天卖的我i天是不允许买入的,所以我必须得是i-2天手里就没有持有了。所以我们来看看这道题怎么做
这一道题参考了https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/discuss/108870/Most-consistent-ways-of-dealing-with-the-series-of-stock-problems 中的解法。

class Solution{
	int maxProfit_with_cool(int[] prices) {
    	int n = prices.length;
    	int dp_i_0 = 0, dp_i_1 = Integer.MIN_VALUE;
    	int dp_pre_0 = 0; // 代表 dp[i-2][0]
    	for (int i = 0; i < n; i++) {
        	int temp = dp_i_0;
        	dp_i_0 = Math.max(dp_i_0, dp_i_1 + prices[i]);
        	dp_i_1 = Math.max(dp_i_1, dp_pre_0 - prices[i]);
        	dp_pre_0 = temp;
    	}
    	return dp_i_0;
	}
}

Best Time to Buy and Sell Stock with Transaction Fee

这一题有一点不一样,就是每一次买卖会收取一次手续费,整体和之前没有太大的变化

class Solution {
    public int maxProfit(int[] prices, int fee) {
        int n = prices.length;
        int dp_i_0 = 0, dp_i_1 = Integer.MIN_VALUE;
        for(int i = 0; i < n; i++){
            int temp = dp_i_0;
            dp_i_0 = Math.max(dp_i_0,dp_i_1+prices[i]);
            dp_i_1 = Math.max(dp_i_1,temp-prices[i]-fee);
        }
        return dp_i_0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值