股票利益最大化(贪心算法及动态规划)

本文介绍了两种解决股票交易问题的方法:贪心算法和动态规划。贪心算法通过比较相邻两天的股票价格,选择在价格上升时买入并卖出获取最大利润。动态规划则使用二维数组记录每天持有和不持有股票的最大利润,通过递推公式更新状态。最终,这两种方法都以O(n)的时间复杂度找到最大收益。
摘要由CSDN通过智能技术生成

题目来源于力扣–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;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值