基础算法 -- 贪心算法

题目描述:

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

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

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

示例 1:输入: [7,1,5,3,6,4]
输出: 7
示例 2:输入: [1,2,3,4,5]
输出: 4
示例 3: 输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int profit = 0;
        bool already_buy = false;
        int buy_price = 0;
        int i = 0;
        for(; i < prices.size()-1; i++){
          if(prices[i] < prices[i+1] && !already_buy) {
            buy_price = prices[i];
            already_buy = true;
            continue;
          }
          if(prices[i] > prices[i+1] && !already_buy) continue;
          if(prices[i] < prices[i+1] && already_buy) continue;
          if(prices[i] > prices[i+1] && already_buy) {
            int tmpprofit = prices[i] - buy_price;
            profit =profit+tmpprofit;
            already_buy = false;
            continue;
          }
        }
      if(already_buy){
          int tmp = prices[i] -buy_price;
          profit = profit+tmp;
      } 
      return profit;
    }
};

我写的时候想法很简单, 遍历一下,遇低则买,遇高则等,再遇低才考虑在上一次卖出, 因此需要每次访问两个变量; 本来觉得效果已经很好了,官网给出的讲解算是又上升了一个层面;

官网的讲解:

由于股票的购买没有限制,因此整个问题等价于寻找 x 个不相交的区间 (l_i,r_i](li ,ri ] 使得如下的总价格最大化; 在li时买入,在ri时卖出; 这里的x就代表了交易次数(一次买入和卖出表示一次交易)

但是对于每一个这样的区间,其最后的收益总和, 等价于每一个跨度为1 的小区间的差值总和; 例如:

[6 1 3 2 4 7] 对于这组数据,我们能找到两次交易机会,[1, 3] 和[2,7]

而第二次交易机会的总收益 7-2 = 5, 与 [2 , 4] + [4, 7] 这两个区间的差值和; 

基于这个想法, 官方给出的贪心算法相当简单; 将寻找大区间的问题转换成了寻找每一个小的增区间;

class Solution {
public:
    int maxProfit(vector<int>& prices) {   
        int ans = 0;
        int n = prices.size();
        for (int i = 1; i < n; ++i) {
            ans += max(0, prices[i] - prices[i - 1]);
        }
        return ans;
    }
};

看到一个关于贪心算法思路的讲解, 很适合今天的这道题:

  • 建立数学模型来描述问题
  • 把求解的问题分成若干个子问题
  • 对每个子问题求解,得到子问题的局部最优解
  • 把子问题的解局部最优解合成原来问题的一个解

如何判断一个题是否适合使用贪心算法:

对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解;

REF:

五大常用算法之一 贪心算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值