首页 > 其他分享 >买卖股票的最佳实际问题

买卖股票的最佳实际问题

时间:2024-12-11 10:24:20浏览次数:5  
标签:std 买卖 int ++ maxProfit 最佳 prices 实际 dp

买卖股票的最佳时机问题

问题介绍

给定一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候最多只能持有一股股票。你也可以先购买,然后在同一天 出售。返回你能获得的最大利润。

解题思路

暴力法、贪心算法、动态规划法

暴力法

for (int i = start; i < prices.size(); i++) {
    for (int j = i + 1; j < prices.size(); j++) {

外层循环从 start 开始,遍历 prices 向量,每次循环选择一个买入日 i。内层循环从买入日 i 的下一个元素开始遍历 prices,选择一个卖出日 j

if (prices[j] > prices[i]) {

如果卖出日 j 的价格高于买入日 i 的价格,则计算利润。

int profit = prices[j] - prices[i] + maxProfitBruteForceHelper(prices, j + 1);

计算利润 profit,等于当前卖出价格减去买入价格,再加上从卖出日 j+1 之后可以获得的最大利润。通过递归调用 maxProfitBruteForceHelper 函数计算。

maxProfit = std::max(maxProfit, profit);

将当前计算的利润与之前的最大利润比较,取较大者作为新的最大利润。

贪心算法

for (int i = 1; i < prices.size(); i++) {
    if (prices[i] > prices[i - 1]) {
    	maxProfit += prices[i] - prices[i - 1];
	}
}

从第2天开始,遍历 prices 向量。注意索引从1开始,这是因为我们需要比较相邻两天的价格。如果第 i 天的价格高于第 i-1 天的价格,就计算这两天的差价并加到 maxProfit 中。这个过程的核心思想是,只要今天的价格高于昨天的价格,就意味着可以买昨天的股票并在今天卖出赚取利润。

动态规划法

int maxProfitDP(std::vector<int>& prices) {
    int n = prices.size();
    if (n <= 1) return 0;

    std::vector<int> dp(n, 0);

    for (int i = 1; i < n; ++i) {
        dp[i] = dp[i - 1];
        for (int j = 0; j < i; ++j) {
            dp[i] = std::max(dp[i], prices[i] - prices[j] + (j >= 2 ? dp[j - 1] : 0));
        }
    }
    return dp[n - 1];
}

获取价格向量的大小 n。如果天数小于等于1,直接返回0,因为无法进行买卖。定义一个大小为 n 的动态规划数组 dp,并初始化为0。dp[i] 表示从第1天到第i天的最大利润。外层循环从第2天开始遍历价格向量。内层循环遍历从第1天到第i天的所有可能买入日 j。对于每一个 i,计算利润:prices[i] - prices[j] 表示第 i 天卖出和第 j 天买入的利润。如果 j >= 2,表示可以进行另一次交易,则再加上 dp[j - 1]。dp[i] = dp[i - 1] 确保当天不交易时的最大利润。dp[i] = std::max(dp[i], prices[i] - prices[j] + (j >= 2 ? dp[j - 1] : 0)) 更新 dp[i] 为较大的利润。

对比

算例一:

总天数:4

每天的股价:1、6、1、7

暴力法:

最大利润:11;关键操作计数:7

贪心算法:

最大利润:11;关键操作计数:3

动态规划法:

最大利润:11;关键操作计数:6

算例二:

总天数:6

每天的股价:7、1、5、3、6、4

暴力法:

最大利润:7;关键操作计数:19

贪心算法:

最大利润:7;关键操作计数:5

动态规划法:

最大利润:7;关键操作计数:15

算例三:

总天数:10

每天的股价:100、180、260、310、40、535、695、140、360、220

暴力法:

最大利润:1085;关键操作计数:352

贪心算法:

最大利润:1085;关键操作计数:9

动态规划法:

最大利润:1085;关键操作计数:45

总结

暴力法 (Brute Force):

  • 时间复杂度: O(n^2) 到 O(n!)
  • 优点: 简单直接,易于理解和实现。
  • 缺点: 由于需要遍历所有可能的买卖组合,时间复杂度很高,性能很差,尤其对于大规模数据集不适用。

贪心法 (Greedy):

  • 时间复杂度: O(n)
  • 优点: 高效,适用于大规模数据集。实现简单,只需一次遍历。
  • 缺点: 只适用于某些特定情况下的问题,如每一天的价格上涨/下降趋势明显的情况。

动态规划 (Dynamic Programming):

  • 时间复杂度: O(n^2)
  • 优点: 能处理更多复杂情况,比暴力法更高效。可以记录并重用之前的计算结果,避免重复计算。
  • 缺点: 依然比贪心法复杂,对某些特定情况不如贪心法高效。

根据以上三组测试样例的对比,可以发现贪心算法在处理该问题时会比暴力法和动态规划法更有优势,样本越大越能体现其优势。而动态规划法在一定程度上比起暴力法更加高效。

对于大多数实际应用场景,贪心法是效率最高的选择。不过,在一些复杂的情况下,动态规划可能会提供更灵活的解决方案。

#include <iostream>
#include <vector>
#include <algorithm>

// 声明全局计数器
int bruteForceComparisonCount = 0;
int greedyComparisonCount = 0;
int dpComparisonCount = 0;

// Brute Force Algorithm
int maxProfitBruteForceHelper(std::vector<int>& prices, int start) {
    int maxProfit = 0;
    for (int i = start; i < prices.size(); i++) {
        for (int j = i + 1; j < prices.size(); j++) {
            bruteForceComparisonCount++; // 每次进行比较时计数器加一
            if (prices[j] > prices[i]) {
                int profit = prices[j] - prices[i] + maxProfitBruteForceHelper(prices, j + 1);
                maxProfit = std::max(maxProfit, profit);
            }
        }
    }
    return maxProfit;
}

int maxProfitBruteForce(std::vector<int>& prices) {
    return maxProfitBruteForceHelper(prices, 0);
}

// Greedy Algorithm
int maxProfitGreedy(std::vector<int>& prices) {
    int maxProfit = 0;
    for (int i = 1; i < prices.size(); i++) {
        greedyComparisonCount++;
        if (prices[i] > prices[i - 1]) {
            maxProfit += prices[i] - prices[i - 1];
        }
    }
    return maxProfit;
}

// Dynamic Programming Algorithm
int maxProfitDP(std::vector<int>& prices) {
    int n = prices.size();
    if (n <= 1) return 0;

    std::vector<int> dp(n, 0);

    for (int i = 1; i < n; ++i) {
        dp[i] = dp[i - 1];
        for (int j = 0; j < i; ++j) {
            dpComparisonCount++;
            dp[i] = std::max(dp[i], prices[i] - prices[j] + (j >= 2 ? dp[j - 1] : 0));
        }
    }
    return dp[n - 1];
}

int main() {
    int n;
    std::cout << "Enter the number of days: ";
    std::cin >> n;
    std::vector<int> prices(n);
    std::cout << "Enter the prices: ";
    for (int i = 0; i < n; ++i) {
        std::cin >> prices[i];
    }

    // 调用并输出各算法结果和计数器值
    std::cout << "Max Profit (Brute Force): " << maxProfitBruteForce(prices) << std::endl;
    std::cout << "Number of Comparisons (Brute Force): " << bruteForceComparisonCount << std::endl;

    std::cout << "Max Profit (Greedy): " << maxProfitGreedy(prices) << std::endl;
    std::cout << "Number of Comparisons (Greedy): " << greedyComparisonCount << std::endl;

    std::cout << "Max Profit (DP): " << maxProfitDP(prices) << std::endl;
    std::cout << "Number of Comparisons (DP): " << dpComparisonCount << std::endl;

    return 0;
}

标签:std,买卖,int,++,maxProfit,最佳,prices,实际,dp
From: https://www.cnblogs.com/linuskou/p/18598766

相关文章

  • 【GreatSQL优化器-06】条件过滤导致选择非最佳
    【GreatSQL优化器-06】条件过滤导致选择非最佳一、condition_fanout_filter导致计划非最佳GreatSQL的优化器对于join的表需要根据行数和cost来确定最后哪张表先执行哪张表后执行,这里面就涉及到预估满足条件的表数据,condition_fanout_filter会根据一系列方法计算出一个数据......
  • 智简模型,边缘智能:AI 轻量化与边缘计算的最佳实践
    文章目录摘要引言模型轻量化与优化方法模型量化模型剪枝知识蒸馏合理使用边缘计算硬件轻量化图像分类实战1.模型量化2.知识蒸馏3.学生模型的创建与训练QA环节总结参考资料摘要边缘计算与AI模型的结合,能够在资源受限的环境中提供实时智能服务。通过模型轻量......
  • Teable 团队 Sealos 最佳实践,创业公司的完美选择
    大家好,我是开源多维表格项目Teable的创始人陈加贝。作为飞书多维表格的最早期负责人,我参与并见证了这个产品从0到1的全过程。这段经历也让我深入理解了企业在数据协作方面的真实需求。以Airtable和Notion为代表的电子表格数据库,展现了一个令人兴奋的方向:让不懂代码的......
  • 运维实战:K8s 上的 Doris 高可用集群最佳实践
    首发:运维有术今天我们将深入探讨::如何在K8s集群上部署Computestoragecoupled(存算耦合)模式的Doris高可用集群?本文,我将为您提供一份全面的实战指南,逐步引导您完成以下关键任务:配置DorisConfigMap:实现自定义配置文件配置DorisSecret:管理特殊密码配置DorisService:......
  • 电容在实际电路中的作用
    电容的特性:电容两端电压不能实现突变,但是两端电压可以同时突变利用电容的储能特性实现上电延迟:利用电容储能特性实现延迟断电:根据电容两端电压不能实现突变的特性,可以解决电平坠落的问题电容的作用还可以当作低通滤波器,降低高频率的噪声,平滑信号......
  • 腾讯通RTX最佳升级迁移指南,兼容移动端及Linux系统
    一、腾讯通RTX继续使用的难题自腾讯通RTX停止更新并下架官网后,用户面临一系列无法解决的问题。以下问题尤其突出:●不支持国产系统与移动端:腾讯通RTX仅适配Windows和Mac系统,不兼容统信UOS、银河麒麟等国产操作系统,也不支持移动端设备使用。●组织架构更新不及时:在频繁调整组织......
  • 从模型到实际:人工智能项目落地的关键要素
    引言近年来,人工智能技术从实验室走向实际应用,其潜力在各行各业得到了初步的验证。然而,AI技术的落地并非一蹴而就,许多企业在尝试部署AI项目时,却发现自己陷入了“模型很好看,应用却难做”的困境。无论是数据准备不足、算法与场景的不匹配,还是缺乏持续优化的机制,这些问题都可能......
  • API设计最佳实践:如何构建易于扩展和维护的RESTful API
    在当今的应用程序开发中,RESTfulAPI已经成为最流行的通信协议之一。REST(RepresentationalStateTransfer)是一种轻量级的架构风格,它利用HTTP协议进行数据传输,广泛用于前后端分离的系统中。构建一个高效、易于扩展且易于维护的RESTfulAPI,不仅能提升系统的可用性,还能为开发团队......
  • Linux 关于df 后目录异常大,却找不到实际大文件的解决办法
    一、通常情况下,有些进程仍在执行已删除文件会导致目录异常大,可以通过以下命令处理。#查看哪些进程占用磁盘空间lsof|grepdeleted或者lsof+L1#杀死占用已删除文件的进程kill-9<pid>二、由于根目录底下有个test子目录中有大文件未删除,就在test目录挂载另一块磁盘;此时......
  • 大数据平台Bug Bash大扫除最佳实践
    作者:尹伟背景目前大促备战常见备战工作:专项压测(全链路压测、内部压测)、灾备演练、降级演练、限流、巡检(监控、应用健康度)、混沌演练(红蓝对抗),如下图所示。随着平台业务越来越复杂,红蓝对抗的作用愈来愈明显,下面将详细介绍大数据平台在本次双十一大促备战工作中是如何开展红蓝对抗......