恒生电子2023年实习春招笔试第二题(编程)

最近写了恒生电子的笔试,故在此记录.....

题目:股票

题目大概是:

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

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

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

其中本金M为10000元,给定股票价格的7天变化即prices数组:[1.0,2.0,1.0,2.0,2.0,3.0,2.0](这里开始与leetcode上的股票题不一样了)求出最大利润。

思路:这题我使用动态规划的思路。

第一步:定义dp数组的意义:

其中dp[i][0]我定义为第i天所持有的股票数,dp[i][1]定义为第i天不持有股票时所能获得的现金数。

第二步:确定递归公式

dp[i][0] =max(dp[i-1][0],dp[i-1][1]/prices[i]);这样做可以保证在变化的股市里能拿到最值得的股票数。其中dp[i-1][0]就是第i-1天我手中的股票数,dp[i-1][1]/prices[i]表示的就是我第i-1天不持有股票时的现金数去除当天的股价就可以得到股票数。通俗来讲就是我用现在的钱去买现在股市的股票是不是能获得更多,比我之前握在手中不卖会不会更值。

dp[i][1] = max(dp[i - 1][1], dp[i - 1][0]*prices[i]);要么就是延续之前的状态即dp[i-1][1],要么就是将前一天手中的股票给卖了(dp[i - 1][0]*prices[i]),两个求较大值。

第三步:初始化dp[][]数组:

其中两个状态分别是初始时的股票数dp[0][0]与现金数dp[0][1]。dp[0][0] =M/prices[0];//初始持有股票数
dp[0][1] = M;//最开始就为本金M=10000元

第四步:确定遍历顺序:

由题可知dp[i][1]的求出需要依赖dp[i-1][1]与dp[i-1][0]。所以从左向右遍历。

第五步:举例推导:prices[i]={1.0,2.0,1.0,2.0,2.0,3.0,2.0}注意推导从prices[1]开始

dp[1][0]=max(10000股,5000股)=10000股;

dp[1][1]=max(10000元,20000元)=20000元;

dp[2][0]=max(dp[1][0],dp[1][1]/prices[2])=20000股

dp[2][1]=max(dp[1][1],dp[1][0]*prices[2])=20000元

dp[3][0]=20000股

dp[3][1]=max(dp[2][1],dp[2][0]*prices[3])=40000元

dp[4][0]=20000股

dp[4][1]=40000元

dp[5][0]=max(20000,40000/3.0)=20000股

dp[5][1]=max(40000,20000*3.0)=60000元

dp[6][0]=max(20000,60000/2.0)=30000股

dp[6][1]=max(60000,30000*2.0)=60000元

即dp[6][1]为最大毛利润。

其中可以看到dp[5][1]与dp[6][1]所求的值一样,这是因为我们只知道7天的股市变化,而dp[6][1]就是把之前赚到的钱在最后一天里继续全部买下股票,然后再在当天继续卖出,等于是没有赚。赚的钱还是之前你所赚的。

代码如下:

#include<iostream>
#include<vector>
using namespace std;
double M=10000.0;
double maxProfit(vector<double>& prices) {
    int len = prices.size();
    vector<vector<double>> dp(len, vector<double>(2, 0));
    dp[0][0] =M/prices[0];//持有股票数
    dp[0][1] = M;//卖出股票所得现金
    for (int i = 1; i < len; i++) {
        dp[i][0] =max(dp[i-1][0],dp[i-1][1]/prices[i]); //锁定最值得的股票数
        dp[i][1] = max(dp[i - 1][1], dp[i - 1][0]*prices[i]);//即获得的毛利润
    }
    return dp[len - 1][1];//最大毛利润
}
int main() {
    vector<double>p = {1.0,2.0,1.0,2.0,2.0,3.0,2.0};
    cout<<maxProfit(p)-M;


}

结果:50000;dp[len-1][1]-M:即为纯利润。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值