股票交易系列 (Eazy - Hard)

前言

自己之前也是在简书写文章,后来发现了 SegmentFault ,感觉挺不错的,写作和阅读方面比简书要方便得多,所以决定来试一下,之前也写过类似 OJ专题 系列文章,从今天开始准备迁移过来,好了下面开始正文

LeetCode 中股票系列问题,前两题较容易,后两题难度远高于前两题,类型差不多,也是在网上大牛的参考下,才得以解决和消化,以下为系列四题的解题思路,并附上算法源码 GitHub 17/05/20

Best Time to Buy and Sell Stock I (Eazy)

问题描述

给出一段股票行情记录,现在可以进行一次买卖交易,求利润最大值

Examples
Input
[7, 1, 5, 3, 6, 4]
Output
The answer is 6 - 1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)

算法思路

  • 从头买入,遍历卖出点

  • 若利润小于零,则可认为该点比旧买入点更小,应该重新从该点买入

  • 若利润大于历史最高利润,则记录最高利润

AC 代码

int maxProfit(vector<int>& prices) {
    if (prices.size() == 0) {
        return 0;
    }
    int max = 0;
    int start = 0;
    for (int i = 0; i < prices.size(); i++) {
        int dif = prices[i] - prices[start];
        if (dif <= 0) {
            start = i;
        } else {
            if (dif > max) {
                max = dif;
            }
        }
    }
    return max;
}

Best Time to Buy and Sell Stock II (Eazy)

问题描述

给出一段股票行情记录,不限制交易次数,求利润最大值

算法思路

利用贪心思想,每天都买入卖出,最终局部最优解之和则为全局最优解

AC 代码

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

Best Time to Buy and Sell Stock III (Hard)

问题描述

给出一段股票行情记录,现在至多可进行两次买卖交易,求利润最大值

算法思路

该题和第四题是一样的,见问题 IV

Best Time to Buy and Sell Stock IV (Hard)

问题描述

给出一段股票行情记录,现在至多可进行 k 次买卖交易,求利润最大值

Examples
Input
2
[7, 1, 5, 3, 6, 4]
Output
(5 - 1) + (6 - 3) = 7

算法思路

这题也是参考了网上大神们的思想,这种解法并不关心你的 k 次交易是从哪天买入和卖出的,只关心 今天的利润以往的最高利润 到底哪个利润大,此处要设两个 DP 变量:

  • 局部最高利润:从 i0 天到 i 天,并在 i 天卖出的最高利润

  • 全局最高利润:从 i0 天到 i 天的最高利润

DP

  • 一天一天遍历

  • 局部最高利润有两种可能

    1. 要么是 今天的利润昨天的局部最高利润 之和

    2. 要么是 今天的利润昨天的全局最高利润 之和

  • 全局最高利润也有两种可能

    1. 要么是 昨天的全局最高利润

    2. 要么是 今天的局部最高利润

Hint

LeetCode 的 OJ 提供的校验数据中,有故意将 k 设置成很大,而天数又很小的测验数据,因此在这里需要优化,否则将报出 RuntimeException

k 很大时,也就相当于问题 II,可以买无数次,利用之前的贪心解法就能 AC 了

AC 代码

int maxProfit(int k, vector<int> &prices) {
    if (prices.empty()) {
        return 0;
    }
    if (k >= prices.size()) {
        return solveMaxProfit(prices);
    }
    int g[k + 1] = {0};
    int l[k + 1] = {0};
    for (int i = 0; i < prices.size() - 1; ++i) {
        int diff = prices[i + 1] - prices[i];
        for (int j = k; j >= 1; --j) {
            l[j] = max(g[j - 1] + max(diff, 0), l[j] + diff);
            g[j] = max(g[j], l[j]);
        }
    }
    return g[k];
}

int solveMaxProfit(vector<int> &prices) {
    int res = 0;
    for (int i = 1; i < prices.size(); ++i) {
        if (prices[i] - prices[i - 1] > 0) {
            res += prices[i] - prices[i - 1];
        }
    }
    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值