题目来源于力扣–https://leetcode-cn.com/
1.可以多次买卖一支股票
2.不能参加多笔交易,买之前需要把之前的股票卖掉
贪心算法实现
原理:只要第二天比第一天的股价贵,能赚钱的就买下来,然后第二天卖掉。否则的话就不买。
main函数下的代码
#include<stdio.h>
int maxProfit(int* prices, int pricesSize);
int max(int a,int b);
int main(){
// 初始化一个股票价格数组
int prices[5] = {7,2,4,9,5};
int profit = maxProfit(prices,5);
printf("%d",profit);
return 0;
}
贪心算法实现部分的代码
时间复杂度O(n)
int maxProfit(int* prices, int pricesSize){
int profit = 0;
for(int i = 0;i<pricesSize-1;i++){
// 第二天的股票价格大于第一天 买入 再卖掉
if(prices[i]<prices[i+1]){
// 卖掉的钱减去买掉的钱 就是利润
profit = profit+prices[i+1]-prices[i];
}
}
return profit;
}
动态规划
动态规划这个方法,在看过解析之后,慢慢理解的一种方式,需要通过对问题进行分析,然后建立递推关系,大的问题由子问题组成,需要通过子问题来解决。首先来分析这个题目,到第i天的时候,你手里要么有股票,要么就没有股票,因此假设有一个二维数组maxProfit[i][0]表示第i天的交易完成后手里没有股票的最大利润,maxProfit[i][1]表示第i天的交易完成后手里持有股票的最大利润。
一、分析手里没有股票:1、今天你把股票卖了。(前一天的持有股票的利润+卖掉的)2、前一天就没有股票。(前一天的最大利润)
二、手里持有股票:1、今天你买了股票。(前一天的最大利润-今天的股票价格)2、前一天就有股票。(前一天的最大利润)这样的话,递推公式就很简单的可以写出来了。
今天手里没有股票的递推公式,选择其中最大的
maxProfit[i][0]=max{maxProfit[i-1][1]+price[i],maxProfit[i-1][0]}
今天手里有股票的递推公式,选择其中最大的
maxProfit[i][1]=max{maxProfit[i-1][0]-price[i],maxProfit[i-1][1]}
最后肯定是手里没有股票的利润大于手里有股票的利润 返回 maxProfit[i][0]
递推公式有了之后,解决的大问题需要子问题解决,由低向上解决问题,这就需要我们寻找初始化条件。
i初始为0,maxProfit[0][0] = 0,maxProfit[0][1] = -price[0]
这样代码就很容易写出来了
时间复杂度O(n)
// 动态规划实现
int maxProfit(int* prices, int pricesSize){
int maxProfit[pricesSize][2];
// 第一天没有持有股票的最大利润
maxProfit[0][0] = 0;
// 第一天买了股票的最大利润
maxProfit[0][1] = -prices[0];
// 递推公式 由低向上求解
for(int i=1;i<pricesSize;i++){
maxProfit[i][0] = max(maxProfit[i-1][0],maxProfit[i-1][1]+prices[i]);
maxProfit[i][1] = max(maxProfit[i-1][1],maxProfit[i-1][0]-prices[i]);
}
// 返回卖掉的最大利润
return maxProfit[pricesSize-1][0];
}
// 判断两个数的最大值
int max(int a,int b){
return a>b?a:b;
}
看递推公式当天的最大利润只与前一天的有关系,可以不用存储其余天的最大利润,不需要数组来存储,换成变量存储前一天的最大利润即可。
int maxProfit(int* prices, int pricesSize){
// 第一天没买的
int maxProfit0 = 0;
// 第一天买了股票的最大利润
int maxProfit1 = -prices[0];
// 递推公式 由低向上求解
for(int i=1;i<pricesSize;i++){
// 新一天没持有股票的最大利润
int newMaxProfit0 = max(maxProfit1+prices[i],maxProfit0);
// 新一天持有股票的最大利润
int newMaxProfit1 = max(maxProfit0-prices[i],maxProfit1);
// 将新一天没持有股票的最大利润赋值给前一天
maxProfit0 = newMaxProfit0;
// 将新一天持有股票的最大利润赋值给前一天
maxProfit1 = newMaxProfit1;
}
// 返回卖掉的最大利润
return maxProfit0;
}
// 判断两个数的最大值
int max(int a,int b){
return a>b?a:b;
}