力扣60天打卡(第5天)

122. 买卖股票的最佳时机 II

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

示例 1:

输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
     随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
     总利润为 4 + 3 = 7 。

示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
     总利润为 4 。

示例 3:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。

提示:

  • 1 <= prices.length <= 3 * 104
  • 0 <= prices[i] <= 104

 解法一:

贪心法:

贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。

解题思路:

买卖股票的策略:

单独交易日:设今日的股票价钱为p1,明天的股票价钱为p2,假设第二天卖出,则收入或亏损为p2-p1

连续上涨交易日:

设此上涨交易日股票价格分别为p1,p2,p3,p4......pn,则pn-p1;等价于每天都买卖,即pn-p1=(p2-p1)+(p3-p2)+......+(pn-pn-1)

连续下降交易日:

不买卖,否则会亏钱。

算法流程: 

遍历整个股票的交易价格,如果后一天的价格比前一天的多,那就前一天买,后一天卖,否则,不进行买卖交易。

int maxProfit(int* prices, int pricesSize){
    int i;
    int total=0;
    for(i=0;i+1<pricesSize;i++)
    {
        if(prices[i]<prices[i+1])
        {
            total=total+prices[i+1]-prices[i];

        }
    }
    return total;

}

 解法二:

类动态规划

​​​​​​​递归法:

int maxProfit(int* prices, int pricesSize){
    if(pricesSize<=1)
    {
        return 0;
        
    }
    int max=0;
    int profit;
 //max(//1.假设最后一天不卖
 //[7,1,5,3,6,4]<=>[7,1,5,3,6]<=>maxProfit(prices,5)
 profit=maxProfit(prices,pricesSize-1);
 if(max<profit)
 {
     max=profit;
 }
 //2.假设最后一天卖
 //max(
//    [7,1,5,3,6]+(6,4)<=>maxProfit(prices,5)+prices[5]-prices[4]
//    [7,1,5,3]+(3,4)<=>maxProfit(prices,4)+prices[5]-prices[3]
 //    [7,1,5]+(5,4)<=>maxProfit(prices,3)+prices[5]-prices[2]
  //    [7,1]+(1,4)<=>maxProfit(prices,2)+prices[5]-prices[1]
  //    [7]+(7,4)<=>maxProfit(prices,1)+prices[5]-prices[0]
  //)
  for(int i=1;i<=pricesSize-1;i++)
  {
      profit=maxProfit(prices,i)+prices[pricesSize-1]-prices[i-1];
      if(max<profit)
      {
          max=profit;
      }
  }
  return max;
//)

}

 非递归法:

int maxProfit(int* prices, int pricesSize){
    if(pricesSize<=1)
    {
        return 0;

    }
    int profits[pricesSize+1];
    profits[1]=0;
    for(int k=2;k<=pricesSize;k++){
    int max=0;
    int porfit;
 //max(//1.假设最后一天不卖
 //[7,1,5,3,6,4]<=>[7,1,5,3,6]<=>maxProfit(prices,5)
 porfit=profits[k-1];
 if(max<porfit)
 {
     max=porfit;
 }
 //2.假设最后一天卖
 //max(
//    [7,1,5,3,6]+(6,4)<=>maxProfit(prices,5)+prices[5]-prices[4]
//    [7,1,5,3]+(3,4)<=>maxProfit(prices,4)+prices[5]-prices[3]
 //    [7,1,5]+(5,4)<=>maxProfit(prices,3)+prices[5]-prices[2]
  //    [7,1]+(1,4)<=>maxProfit(prices,2)+prices[5]-prices[1]
  //    [7]+(7,4)<=>maxProfit(prices,1)+prices[5]-prices[0]
  //)
  for(int i=1;i<=k-1;i++)
  {
      porfit=profits[i]+prices[k-1]-prices[i-1];
      if(max<porfit)
      {
          max=porfit;
      }
  }
  profits[k]=max;
}
//)
return profits[pricesSize];
}

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
力扣题礼盒的最大天密度问题可以转化为一个函数 f(x) 的形式,其中 f(x) 表示 "礼盒中最大天数不超过 x" 这个条件下的天密度。 具体地,对于一个给定的天数 x,我们可以使用贪心算法来判断在不超过 x 的情况下,最多能拿到多少天的礼盒。假设当前已经拿到了 k 个礼盒,其天数分别为 d1, d2, ..., dk,且满足 d1 <= d2 <= ... <= dk。此时,我们可以从剩余的礼盒中选择一个最小的天数大于 dk 的礼盒,加入到已拿到的礼盒中,直到不能再加入礼盒为止。这个贪心算法的时间复杂度是 O(nlogn),其中 n 是礼盒的数量。 对于一个给定的天数 x,如果能拿到的最多天数不超过 x,则 f(x) 为 true,否则 f(x) 为 false。这个函数的曲线是一个阶梯状的函数,如下图所示: ``` | | | | | | | | | | |___|___|___|___ x1 x2 x3 x4 ``` 其中,每个竖直的线段表示一个礼盒,x1、x2、x3、x4 分别表示四个礼盒的最大天数,每个水平的线段表示函数值为 true 的区间。例如,当 x 取值在 [x3, x4] 区间内时,f(x) 的值都为 true,因为在不超过 x3 的情况下,最多能拿到的天数为 3+4+4=11,不超过 x4 的限制。 我们要找到的最大的天密度,就是最后一个函数值为 true 的点所对应的 x 值,即 x4。这个问题可以通过二分查找法解决,每次取中间值,判断中间值是否满足条件,然后不断缩小搜索区间,最终找到最大的 x 值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IKUN家族

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值