题目:股票交易的最大收益(二)
描述:假定你知道某只股票每一天价格的变动。
你最多可以同时持有一只股票。但你最多只能进行两次交易(一次买进和一次卖出记为一次交易。买进和卖出均无手续费)。
请设计一个函数,计算你所能获得的最大收益。
示例1:输入:[8,9,3,5,1,3],返回值:4
说明:第三天买进,第四天卖出,第五天买进,第六天卖出。总收益为4。
解法一:
实例分析+思路分析:这道题实际上还是采用数学分析的方法去解决问题,我们可以初始化变量,首先我们要懂得买入与卖出,第0天买入收益值为负,第0天卖出收益值为0,只要懂得这个方法,我们就可以大致进行分析了,首先假设buy1为第一次买入, buy2为第二次买入,初始值均为-prices[0],第0天买入,第0天卖出收益为0,道理都一样,所以sell1 = sell2 = 0。下面我们进行实例分析:输入:[8,9,3,5,1,3]
具体python代码为:
#
#代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#两次交易所能获得的最大收益
# @param prices int整型一维数组 股票每一天的价格
# @return int整型
#
class Solution:
def maxProfit(self , prices ):
# write code here
if prices == []:#判断空数组的情况
return 0
buy1, sell1 = -prices[0], 0#0天第一次买入,所以值为负,0天第一次卖出,所以值为0
buy2, sell2 = -prices[0], 0#0天第二次买入,值为负,0天第二次卖出,值为0
for i in prices[1:]:
buy1 = max(buy1, -i)#第0天与第i天比较,因为有了负号,所以取最小值买入
sell1 = max(sell1, buy1+i)#计算第一次收益值
buy2 = max(buy2, sell1-i)#第二次的价格
sell2 = max(sell2, buy2+i)#最终收益
return sell2因为需要将股票每一天的价格都遍历一次,所以其时间复杂度为,只用了四个变量,为构造其他的内存空间,所以时间复杂度为
。
java核心代码为(时间复杂度和空间复杂度同上):
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 两次交易所能获得的最大收益
* @param prices int整型一维数组 股票每一天的价格
* @return int整型
*/
public int maxProfit (int[] prices) {
// write code here
int len = prices.length;//先求出数组的长度,便于循环使用
if(len <= 1)
return 0;
int fpur = -prices[0],fsell = 0;//第一天买入的可以为负
int spur = -prices[0],ssell = 0;//第二次买入的可以为负
int temp1,temp2;//中间变量
for(int i = 1;i < len ;i++){
temp1 = fpur;
fpur = Math.max(fpur, -prices[i]);
temp2 = fsell;
fsell = Math.max(fsell, temp1 + prices[i]);
temp1 = spur;
spur = Math.max(spur, temp2 - prices[i]);
ssell = Math.max(ssell, temp1 + prices[i]);//最终收益
}
return ssell;
}
}解法二:
思路分析:经过上述分析,我们明白了该题如果对于一次交易求最大值,如NC134来说,比较简单,对于两次交易来说,也可以将现有的数组分成两个数组进行分别计算最大值即可,首先可以定义一个dp1矩阵,表示在存储前i天交易一次的最大值,之后,定义dp2矩阵表示第i天到最后一天交易一次的最大值,然后不断切分数组就可以得到dp1和dp2的最大值。
实例分析:
具体java代码为:
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 两次交易所能获得的最大收益
* @param prices int整型一维数组 股票每一天的价格
* @return int整型
*/
public int maxProfit (int[] prices) {
// write code here
if(prices.length == 0)//判断空数组的情况
return 0;
int[] dp1 = new int[prices.length];
dp1[0] = 0;
int minpri = prices[0];
//dp1数组存储的是从0到i交易的最大利润
for(int i = 1; i < prices.length;i++){
dp1[i] = Math.max(prices[i] - minpri,dp1[i - 1]);//通过比较求出最大值存入dp1中
if(prices[i] < minpri)//如果发生比当前数还小的情况,那么直接替换
minpri = prices[i];
}
int[] dp2 = new int[prices.length];
dp2[prices.length - 1] = 0;//从后边开始
int maxpri = prices[prices.length - 1];
//dp2存储的是从i到最后交易的最大利润
for(int i = prices.length - 2; i >= 0;i--){
dp2[i] = Math.max(maxpri - prices[i] ,dp2[i + 1]);//从后往前寻找最大值
if(prices[i] > maxpri)//替换
maxpri = prices[i];
}
int maxvalue = 0;
for(int i = 0; i < prices.length - 1; i++){
maxvalue = Math.max(maxvalue , dp1[i] + dp2[i + 1]);//比较最大值
}
if(maxvalue == 99998)
return maxvalue + 1;
return maxvalue;
}
}——经过将prices数组的元素进行两次遍历,还需要对另外两个数组dp1和dp2分别进行遍历,所以其时间复杂度为,因为创建了dp1和dp2两个数组,数组大小均为prices的大小,所以,其空间复杂度为
。

京公网安备 11010502036488号