状态转移类算法题心得体会

题目来源:力扣第188题

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。

注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: [2,4,1], k = 2
输出: 2
解释: 在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。

示例 2:

输入: [3,2,6,5,0,3], k = 2
输出: 7
解释: 在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 ;随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。

 AC代码:

class Solution {
public:
       int maxProfit(int k, vector& prices) {
    	if(prices.size()==0) return 0;
    	if(k>prices.size()/2){
    		int profit=0;
    		bool ifbuy=0;
			for(int i=0;iprices[i+1]&&ifbuy==1){
					profit+=prices[i];
					ifbuy=0;
				}
			} 
			return profit;
		}
                int money[prices.size()][k+1][2];
		for(int i=0;i

思路:

  第4行用于处理天数为0的情况;

  第5行至第24行针对性地处理不需要考虑k的特殊情况(完成一笔交易至少需要买入、卖出两天,若允许的最大交易次数k>总天数/2,则相当于处理这组数据时无需考虑k),提高程序对某些数据的处理速度。

  第25行至第44行,用于处理一般情况:

  用money[i][j][0]表示在第i+1天,剩余可交易j次,且当天收盘后未持有股票的情况下,拥有资金的最大值;

  用money[i][j][1]表示在第i+1天,剩余可交易j次,且当天收盘后持有股票的情况下,拥有资金的最大值;

  设初始时拥有资金为0,资金可以为负数。约定每次买入时,当天剩余可交易次数减一。

  类似数学中的数学归纳法,首先讨论初始状态:

  对于任意剩余交易次数j,money[0][j][0]的值均为0,即第一天未买入股票,无论还能交易几次,当天最多拥有0元;

  对于任意剩余交易次数j,money[0][j][1]的值均为当天的股票价格的相反数,即第一天买入股票,无论还能交易几次,当天最多拥有-prices[i]元;

  另外还需将money[i][k][0]的值初始化为0(i为允许的任意值); 即无论处在第几天,若仍允许的交易次数为最大值k,说明到目前为止未进行任何股票交易,拥有资金仍为0;

  money[i][k][1]则无任何意义,因为不可能出现买入了但剩余可交易次数仍为最大次数的情况。

  之后从初始状态出发不断推导其他状态,通过对money数组的遍历(不考虑j==k的情况,因为在初始状态中已经讨论),便可以得到在任意一天,剩余可交易次数为任意次,此时持有/未持有股票情况下,拥有资金的最大值:

money[i][j][0]=max(money[i-1][j][0],money[i-1][j][1]+prices[i]);
money[i][j][1]=max(money[i-1][j][1],money[i-1][j+1][0]-prices[i]); 

  最终,数据money[prices.size()-1][0][0]即为在最后一天持有资金的最大值,即为能获得的最大利润。

  例如:对于输入[2,4,1],k=2,若使用该一般算法,则首先计算初始值:

  money[0][0][0]=0
  money[0][0][1]=-2
  money[0][1][0]=0
  money[0][1][1]=-2
  money[0][2][0]=0

  接着,讨论第二天的情况,第二天的每一个状态必定由第一天的某个状态变化而来,如money[1][0][0]的上一个状态必定为 money[0][0][0]=0(第1天与第2天均未持有股票)或money[0][0][1](第1天持有股票,在第2天卖出),money[1][0][1]上一个状态必定为money[0][0][1](第1天就已经持有股票,第2天未卖出)或money[0][1][0]=0(第1天未持有股票,第2天消耗一次买入机会买入)。因此,可以通过第一天的状态推导出第二天各个状态的最大取值。

  同理,第n天各个状态的最大取值可由第n-1天各个状态的最大取值推到得到。

  

  

  

 

你可能感兴趣的:(算法)