AI刷题总结与反思——其五|豆包MarsCode AI刷题

96 阅读4分钟

本系列将分享十一月在marscode上遇到的比较有意思的题目供同学们交流分享。

本题也将用到一个很常用的算法——动态规划。

问题描述

小R近期表现出色,公司决定以股票的形式给予奖励,并允许他在市场上进行交易以最大化收益。给定一个数组,数组中的第 i 个元素代表第 i 天的股票价格。小R需要设计一个算法来实现最大利润。

股票交易规则如下:

  • 小R可以多次买卖股票,但在买入新的股票前必须卖出之前的股票。
  • 每次卖出股票后存在一天的冷冻期,在冷冻期内小R不能购买股票。

你的任务是帮助小R计算出在遵守交易规则的情况下能够获得的最大利润。

  • stocks: 一个整数列表,表示连续几天内的股票价格。

测试样例

样例1:

输入:stocks = [1, 2]
输出:1

样例2:

输入:stocks = [2, 1]
输出:0

样例3:

输入:stocks = [1, 2, 3, 0, 2]
输出:3

样例4:

输入:stocks = [2, 3, 4, 5, 6, 7]
输出:5

样例5:

输入:stocks = [1, 6, 2, 7, 13, 2, 8]
输出:12

问题分析

  • 我们已知一个整数数组 stocks,其中每个元素代表对应天数的股票价格。
  • 需要在遵循特定交易规则(可多次买卖,但买入前须卖出且每次卖出后有一天冷冻期)的情况下,设计算法求出能获得的最大利润。

关键算法:

动态规划

  • 本题中会用到变化二位数组,适合用动态规划来解决。我们可以定义几个状态来表示在不同情况下所能获得的最大利润。
  • 设 dp[i][0] 表示第 i 天结束时,处于未持有股票且不在冷冻期的最大利润。
  • 设 dp[i][1] 表示第 i 天结束时,处于持有股票的最大利润。
  • 设 dp[i][2] 表示第 i 天结束时,处于未持有股票且在冷冻期的最大利润。

还需要弄明白 状态转移关系

  • 对于 dp[i][0]

    • 它可以由两种情况转移而来。一种是前一天就处于未持有股票且不在冷冻期的状态,即 dp[i - 1][0];另一种是前一天处于未持有股票且在冷冻期的状态,即 dp[i - 1][2]。所以 dp[i][0] = max(dp[i - 1][0], dp[i - 1][2])
  • 对于 dp[i][1]

    • 它只能由前一天处于未持有股票且不在冷冻期的状态,然后在第 i 天买入股票转移而来。因为买入股票会花费资金,所以利润要减去当天的股票价格,即 dp[i][1] = dp[i - 1][0] - stocks[i]
  • 对于 dp[i][2]

    • 它只能由前一天处于持有股票的状态,然后在第 i 天卖出股票转移而来。因为卖出股票会获得资金,所以利润要加上当天的股票价格,即 dp[i][2] = dp[i - 1][1] + stocks[i]

创建动态规划数组:

int** dp = (int**)malloc(n * sizeof(int*));
    for (int i = 0; i < n; i++) {
        dp[i] = (int*)malloc(3 * sizeof(int));
       }

初始化、填充动态规划数组:

dp[0][0] = 0;
    dp[0][1] = -stocks[0];
    dp[0][2] = 0;

    // 填充动态规划数组
    for (int i = 1; i < n; i++) {
        dp[i][0] = dp[i - 1][0] > dp[i - 1][2]? dp[i - 1][0] : dp[i - 1][2];
        dp[i][1] = dp[i - 1][0] - stocks[i];
        dp[i][2] = dp[i - 1][1] + stocks[i];
    }

    // 计算最大利润
    int max_profit_value = dp[n - 1][0] > dp[n - 1][2]? dp[n - 1][0] : dp[n - 1][2];

    // 释放动态规划数组内存
    for (int i = 0; i < n; i++) {
        free(dp[i]);
    }
    free(dp);

经过上述两步操作,就成功地动态创建了一个二维数组 dp,它有 n 行 3 列,可以用来存储 int 类型的元素,并且可以根据程序的实际需求灵活地指定行数 n,而不像静态二维数组那样在编译时就必须确定数组的大小。

需要注意的是,在使用完动态分配的内存后,要记得使用 free 函数释放这些内存,以避免内存泄漏。

以上便是实现题述功能的关键步骤,我们也认识到二维数组同指针结合后高效的定位、存取能力,也同样体现了C语言的最大特色——指针、内存管理,也是C区别于其他高级语言的特点之一,同学们还应多多学习,努力掌握更多的、高效的有意思的算法,并加以运用到刷题实践中去,在一次一次的反思、巩固中拥抱更强大的自己!

附警句:你所写下的每一行代码都是铺向未来的路。