【cpp算法】买卖股票的最佳时机(122)

本文介绍了如何使用C++编程解决股票买卖问题,通过简单版本和动态规划方法计算在允许最多一笔交易的情况下获取的最大利润。动态规划版本展示了如何利用状态转移方程来优化决策过程。
摘要由CSDN通过智能技术生成

前言

今天继续跟着小浩老师学习算法,由易到难,感觉越来越有意思啦。今天学习算法中的经典问题,股票的买卖。我所用的是非常简单的思路,后续学习了动态规划的思想,其实大二的时候学算法分析与设计这门课的时候就似懂非懂很多东西妹学明白,今天做的这道动态规划的题,我感觉不难而且还蛮有意思的。

题目

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。注意你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]
输出: 7

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

示例 2:

输入: [1,2,3,4,5]
输出: 4

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

​ 注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。

​ 因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例 3:

输入: [7,6,4,3,1]
输出: 0

解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

题目分析:

首先我们看一下题目中给出的两个条件:

1、不能参与多笔交易。换句话讲,我们只能在手上没有股票的时候买入,也就是必须在再次购买前出售掉之前的股票。像我们平时买股票时的追涨杀跌是不可以的。

2、尽可能地多进行交易。这个非常好理解。像是黄金,一年基本上都有2-3次涨跌。我们只要把握住机会,在每一次涨跌的时候,低价卖入高价卖出,就可以使利益达到最大化。这个条件也是相当重要的,如果我们把这里变成,最多完成两笔交易,就变成另一道题。
更多的分析请点击小浩算法----买卖股票的最佳时期 题解分析

代码及思路

简单版

其实最开始我自己的思路挺简单的,能实现这个功能。

我的思路就是:
从第一个元素开始,如果这个元素的后一天的价格大于当前天的价格,那么就卖出去积攒利润,否则就继续遍历,直到倒数第二个元素(这里如果到最后一个会有内存泄漏的问题)
挺简单的对叭哈哈哈哈真的好简单!

值得注意的是,在cpp里面我们使用vector可以在初始化的时候不指定大小,但是需要注意格式。我太爱vector了呵呵

#include<iostream>
#include<vector>
using namespace std;
int main() {
	cout << "请输入总天数:" << endl;
	int amountDays;
	cin >> amountDays;
	int priceDay;
	//指定一个空的vector
	vector<int> stockPriceArray;
	//先输入股票的价格
	for (int i = 0; i < amountDays; i++) {
		cin >> priceDay;
		stockPriceArray.push_back(priceDay);
	}
	//初始化总利润价格为0元
	int amountPrice=0;
	//如果遇到第二天比第一天高,那么就买了在卖,这就是最大的利润
	for (int i = 0; i < amountDays-1; i++) {
		if (stockPriceArray[i] < stockPriceArray[i + 1]) {
			amountPrice = amountPrice + stockPriceArray[i + 1] - stockPriceArray[i];
		}
	}
	cout << amountPrice << endl;
	return 0;
}

动态规划版

动态规划的思想其实最核心的是,我当前的状态的值和我的上一个状态是息息相关的,所以我们需要考虑两个问题:

  1. 我的初始值是什么?
  2. 前一个状态和后一个状态之间的联系怎么确立?

废话不多说,由于我们最后要求的是利润,而且每一天我们都可以选择抛售or保留股票,这样下来每天的不同状态下的利润都是不一样的。

  • 如果我在第i天我的手上有股票,那么我当天的利润值应该分为两个部分:①我前一天有股票,今天没卖出去 (利润:等于前一天有股票的利润)② 我前一天没有股票,今天买进来了(前一天没有股票的利润 - 今天的股票价格
  • 如果我在第i天手上没有股票,那么当天的利润值也应该有两种情况。①我前一天就没有股票(利润,和前一天没有股票一样) ② 我前一天有股票,今天卖了(利润应该等于前一天有股票的利润 + 今天股票的价格
    有没有人觉得这个东西好像神经网络的结构😂因此,我们可以用二维数组来解决上面这个问题。
  • 需要设置初始值,很容易知道 [0][0]位置是第一天不拥有股票,则利润是0,那[0][1]则是第一天拥有股票,利润是-price[1]
#include<iostream>
#include<vector>
using namespace std;
int main() {
	cout << "请输入总天数:" << endl;
	int amountDays;
	cin >> amountDays;
	int priceDay;
	//指定一个空的vector
	vector<int> stockPriceArray;
	//先输入股票的价格
	for (int i = 0; i < amountDays; i++) {
		cin >> priceDay;
		stockPriceArray.push_back(priceDay);
	}
	//设置一个二维数组,对于vector用嵌套来设置,行是第一个形参,列是第二个形参
	vector<vector<int>> dp(stockPriceArray.size(), vector<int>(2));
	//初始化
	dp[0][0] = 0;
	dp[0][1] = -stockPriceArray[0];

	for (int i = 1; i < amountDays; i++) {
		dp[i][0] = max(dp[i - 1][0], dp[i-1][1] + stockPriceArray[i]);
		dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - stockPriceArray[i]);
	}
	cout <<  dp[amountDays-1][0] << endl;
	return 0;

}

好好加油,要学会努力地提升自己coding的能力,把技术学好,加油加油!!

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值