[leetcode] Best Time to Buy and Sell Stock III

本文介绍了一种算法,用于解决股票交易中寻找最佳买卖时机的问题,允许进行最多两次交易以获得最大利润。通过动态规划方法,分别从前向后和从后向前计算潜在的最大收益,并最终确定最优策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

from : https://leetcode.com/problems/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.

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int days = prices.size();
        if(days <= 1) {
            return 0;
        }
        int *left = new int[days]; // left[i]:inlcude ith day, can make most.
        int *right = new int[days];
        
        // for left
        int v = prices[0];
        left[0] = 0;
        for(int i=1; i<days; ++i) {
            if(v > prices[i]) {
                v = prices[i];
            }
            left[i] = max(left[i-1], prices[i] - v);
        }
        
        // for right
        v = prices[days-1];
        right[days-1] = 0;
        for(int i=days-2; i>=0; --i) {
            if(v < prices[i]) {
                v = prices[i];
            }
            right[i] = max(right[i+1], v - prices[i]);
        }
        
        int made = 0;
        for(int i=0; i<days; ++i) {
            if(made < left[i] + right[i]) {
                made = left[i] + right[i];
            }
        }
        
        delete[] left;
        delete[] right;
        return made;
    }
};

public class Solution {
    public int maxProfit(int[] prices) {
        if(prices == null || prices.length < 2) {
            return 0;
        }
        int n = prices.length;
        int[] t1 = new int[n];// t1[i]:在i和i之前卖,最大获利
        int[] t2 = new int[n];// t2[i]:在i和i之后买,最大获利
        
        int a = prices[0];
        int p = 0;
        for(int i=1; i<n; ++i) {
            if(prices[i] < a) {
                a = prices[i];
            }
            if(prices[i] -a >p) {
                p = prices[i]-a;
            }
            t1[i] = p;
        }
        
        a = prices[n-1];
        p = 0;
        for(int i=n-2; i>=0; --i) {
            if(prices[i] > a) {
                a = prices[i];
            }
            if(a - prices[i] > p) {
                p = a-prices[i];
            }
            t2[i] = p;
        }
        
        p = 0;
        for(int i=0; i<n; ++i) {
            if(t1[i]+t2[i] > p) {
                p = t1[i]+t2[i];
            }
        }
        return p;
    }
}


最近被问如何求出买入和卖出点的问题,于是用java写了下面的代码。

package dp;

import java.util.ArrayList;
import java.util.List;

public class StockBaidu {
	class Choice {
		int buyAt;
		int selAt;
		public Choice(int buy, int sel) {
			buyAt = buy;
			selAt = sel;
		} 
	}
	class Profit {
		Choice chioce;
		int sum;
		public Profit(Choice c, int s) {
			chioce = c;
			sum = s;
		}
	}
	public List<Choice> maxProfit(int[] prices) {
		List<Choice> ans = new ArrayList<Choice>();
		int days = prices.length;
		if (days <= 1) {
			return ans;
		}
		Profit[] left = new Profit[days]; // left[i]:inlcude ith day, can make most.
		Profit[] right = new Profit[days];

		// for left
		int k = 0;
		int v = prices[0];
		left[0] = new Profit(new Choice(0, 0),  0);
		for (int i = 1; i < days; ++i) {
			if (v > prices[i]) {
				v = prices[i];
				k = i;
			}
			left[i] = choose(left[i-1], prices[i]-v,  k, i);
		}

		// for right
		k = days - 1;
		v = prices[k];
		right[days - 1] = new Profit(new Choice(days - 1, days - 1),  0);
		for (int i = days - 2; i >= 0; --i) {
			if (v < prices[i]) {
				v = prices[i];
				k = i;
			}
			right[i] = choose(right[i+1], v-prices[i], i, k);
		}

		int made = 0;
		for (int i = 0; i < days; ++i) {
			if (made < left[i].sum + right[i].sum) {
				ans.clear();
				if(left[i].chioce.buyAt < left[i].chioce.selAt) {
					ans.add(left[i].chioce);
				}
				if(right[i].chioce.buyAt < right[i].chioce.selAt) {
					ans.add(right[i].chioce);
				}
				made = left[i].sum + right[i].sum;
			}
		}

		return ans;
	}
	
	public int maximumProfit(int[] prices) {
        int days = prices.length;
        if(days <= 1) {
            return 0;
        }
        int[] left = new int[days];
        int[] right = new int[days];
        
        // for left
        int v = prices[0];
        left[0] = 0;
        for(int i=1; i<days; ++i) {
            if(v > prices[i]) {
                v = prices[i];
            }
            left[i] = Math.max(left[i-1], prices[i] - v);
        }
        
        // for right
        v = prices[days-1];
        right[days-1] = 0;
        for(int i=days-2; i>=0; --i) {
            if(v < prices[i]) {
                v = prices[i];
            }
            right[i] = Math.max(right[i+1], v - prices[i]);
        }
        
        int made = 0;
        for(int i=0; i<days; ++i) {
            if(made < left[i] + right[i]) {
                made = left[i] + right[i];
            }
        }
        
        return made;
    }
	
	private Profit choose(Profit before, int profit, int buyAt, int selAt) {
		if(before.sum >= profit) {
			return before;
		}
		return new Profit(new Choice(buyAt, selAt), profit);
	}
	
	
	public static void main(String[] args) {
		int[] data = {4,1,9,3,6,5,2,1,4,9,3,4,2,5,9};
		int profit = 0;
		for(Choice c : new StockBaidu().maxProfit(data)) {
			profit += data[c.selAt] - data[c.buyAt];
			System.out.println("profit is " + profit);
			System.out.println("buy at " + c.buyAt + ": sell at " + c.selAt);
		}
		System.out.println(new StockBaidu().maximumProfit(data));


		int[] data2 = {9, 2, 6};
		int profit2 = 0;
		for(Choice c : new StockBaidu().maxProfit(data2)) {
			profit2 += data2[c.selAt] - data2[c.buyAt];
			System.out.println("profit is " + profit2);
			System.out.println("buy at " + c.buyAt + ": sell at " + c.selAt);
		}
		System.out.println(new StockBaidu().maximumProfit(data2));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值