Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

领扣-121/122 最佳买卖时机 Best Time to Buy and Sell MD


目录

买卖股票的最佳时机 -121

数组 贪心算法

题目

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

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入股票前卖出股票。

示例 1:

  1. 输入: [7,1,5,3,6,4]
  2. 输出: 5
  3. 解释: 在第 2 天的时候买入,在第 5 天的时候卖出,最大利润 = 6-1 = 5
  4. 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。

示例 2:

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

方法声明:

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. }
  4. }

暴力法

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. int max = 0;
  4. for (int i = 0; i < prices.length; i++) {
  5. for (int j = i + 1; j < prices.length; j++) {
  6. max = Math.max(max, prices[j] - prices[i]);
  7. }
  8. }
  9. return max;
  10. }
  11. }

时间复杂度:O(n^2)

空间复杂度:O(1)

贪心算法(波峰波谷法)

对于这道题,我们很明显能感觉到,不是单纯的找出数组中的最小值和最大值,然后求他们的差的,因为最小值不一定在最大值的前面。

但是也很明显,这道题确实是让我们找最值的,问题出在哪呢?

问题出在,这道题其实是让我们求极小值和极大值的,也即先找出一个波段内的极小值和极大值,然后如果发现另一个更小的极小值后,再找出从此极小值开始后的极大值;最终我们比较的是这些极大值和极小值的差中的最大值。

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. int maxprofit = 0, temMax = 0, minprice = Integer.MAX_VALUE;
  4. for (int i = 0; i < prices.length; i++) {
  5. if (prices[i] < minprice) { //一旦找到更小的值,则开始从此点找极大值
  6. minprice = prices[i]; //始终存的的是已发现的最小值
  7. temMax = 0;//重新开始计算差值(这一步是可以忽略的)
  8. } else {
  9. temMax = prices[i] - minprice;
  10. maxprofit = Math.max(maxprofit, temMax);//和之前的最大利润做比较
  11. }
  12. }
  13. return maxprofit;
  14. }
  15. }

优化

以上逻辑等价于如下形式:

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. int maxprofit = 0, minprice = Integer.MAX_VALUE;
  4. for (int price : prices) {
  5. if (price < minprice) { //一旦找到更小的值,则开始从此点找极大值
  6. minprice = price; //始终存的的是已发现的最小值
  7. } else {
  8. maxprofit = Math.max(maxprofit, price - minprice);//和之前的最大利润做比较
  9. }
  10. }
  11. return maxprofit;
  12. }
  13. }

也等价于如下形式,虽然这种形式代码量小了一些,但这种形式其实计算多个很多:

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. int maxprofit = 0, buy = Integer.MAX_VALUE;
  4. for (int price : prices) {
  5. buy = Math.min(buy, price);
  6. maxprofit = Math.max(maxprofit, price - buy);
  7. }
  8. return maxprofit;
  9. }
  10. }

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

数组 贪心算法

题目

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

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

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

波峰波谷法

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. int maxprofit = 0, minprice = Integer.MAX_VALUE, maxprice = Integer.MAX_VALUE;
  4. boolean findMin = true; //找波谷还是波峰
  5. for (int i = 0; i < prices.length; i++) {
  6. if (findMin) { //找波谷
  7. if (prices[i] < minprice) { //有更低的波谷
  8. minprice = prices[i]; //更新购买价格
  9. maxprice = prices[i];
  10. } else { //比波谷的值大,那么我们就找波峰
  11. maxprice = prices[i]; //更新卖出价格
  12. findMin = false;
  13. }
  14. } else { //找波峰
  15. if (prices[i] > maxprice) { //有更高的波峰
  16. maxprice = prices[i]; //更新卖出价格
  17. } else { //比波峰小,那么我们就在之前卖出,然后在这里买入
  18. maxprofit += (maxprice - minprice); //更新收益
  19. minprice = prices[i]; //重置所有状态
  20. maxprice = prices[i];
  21. findMin = true;
  22. }
  23. }
  24. }
  25. return maxprofit + (maxprice - minprice);//防止最后在找波峰过程中结束,导致没有卖出的问题
  26. }
  27. }

时间复杂度:O(n)

空间复杂度:O(1)

波峰波谷法优化

上面的代码实际上有很多运算时可以忽略的,可以优化为如下逻辑

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. if (prices == null || prices.length <= 1) return 0;
  4. int i = 0, valley = prices[0], peak = prices[0], maxprofit = 0;
  5. while (i < prices.length - 1) {
  6. while (i < prices.length - 1 && prices[i] >= prices[i + 1]) i++; //有更低的波谷
  7. valley = prices[i]; //更新购买价格
  8. while (i < prices.length - 1 && prices[i] <= prices[i + 1]) i++; //有更高的波峰
  9. peak = prices[i]; //更新卖出价格
  10. maxprofit += peak - valley;
  11. }
  12. return maxprofit;
  13. }
  14. }

累加法

我们不需要跟踪峰值和谷值对应的成本以及最大利润,我们可以直接继续增加数组的连续数字之间的差值,如果第二个数字大于第一个数字,我们获得的总和将是最大利润。这种方法将简化解决方案。

例如:[1, 7, 2, 3, 6, 7, 6, 7]

与此数组对应的图形是:

从上图中,我们可以观察到 A+B+C 的和等于差值 D 所对应的连续峰和谷的高度之差。

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. int maxprofit = 0;
  4. for (int i = 1; i < prices.length; i++) {
  5. if (prices[i] > prices[i - 1]) maxprofit += prices[i] - prices[i - 1];
  6. }
  7. return maxprofit;
  8. }
  9. }

买卖股票的最佳时机 III -123

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

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易

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

动态规划 二维数组(不懂)

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. if (prices == null || prices.length <= 1) return 0;
  4. int n = prices.length;
  5. int[][] g = new int[n][3], l = new int[n][3];
  6. for (int i = 1; i < n; i++) {
  7. int diff = prices[i] - prices[i - 1];
  8. for (int j = 1; j <= 2; j++) {
  9. l[i][j] = Math.max(g[i - 1][j - 1] + Math.max(diff, 0), l[i - 1][j] + diff);
  10. g[i][j] = Math.max(l[i][j], g[i - 1][j]);
  11. }
  12. }
  13. return g[n - 1][2];
  14. }
  15. }

动态规划 一维数组(不懂)

  1. class Solution {
  2. public int maxProfit(int[] prices) {
  3. if (prices == null || prices.length <= 1) return 0;
  4. int n = prices.length;
  5. int[] g = new int[3], l = new int[3];
  6. for (int i = 0; i < n - 1; i++) {
  7. int diff = prices[i+1] - prices[i ];
  8. for (int j = 2; j >= 1; j--) {
  9. l[j] = Math.max(g[j - 1] + Math.max(diff, 0), l[j] + diff);
  10. g[j] = Math.max(l[j], g[j]);
  11. }
  12. }
  13. return g[2];
  14. }
  15. }

买卖股票的最佳时机 IV -188

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

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易

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

方法声明

  1. class Solution {
  2. public int maxProfit(int k, int[] prices) {
  3. }
  4. }

动态规划(不懂)

  1. class Solution {
  2. public int maxProfit(int k, int[] prices) {
  3. if (prices == null || prices.length <= 1) return 0;
  4. int n = prices.length;
  5. if (k >= n) return maxProfit(prices);
  6. int[] g = new int[k + 1], l = new int[k + 1];
  7. for (int i = 0; i < n - 1; i++) {
  8. int diff = prices[i + 1] - prices[i];
  9. for (int j = k; j >= 1; j--) {
  10. l[j] = Math.max(g[j - 1] + Math.max(diff, 0), l[j] + diff);
  11. g[j] = Math.max(l[j], g[j]);
  12. }
  13. }
  14. return g[k];
  15. }
  16. public int maxProfit(int[] prices) {
  17. int maxprofit = 0;
  18. for (int i = 1; i < prices.length; i++) {
  19. if (prices[i] > prices[i - 1]) maxprofit += prices[i] - prices[i - 1];
  20. }
  21. return maxprofit;
  22. }
  23. }

2016-12-29

2018-12-16

领扣-121/122/123/188 最佳买卖时机 Best Time to Buy and Sell MD的更多相关文章

  1. 121. 122. 123. 188. Best Time to Buy and Sell Stock *HARD* 309. Best Time to Buy and Sell Stock with Cooldown -- 买卖股票

    121. Say you have an array for which the ith element is the price of a given stock on day i. If you ...

  2. Leetocode7道买卖股票问题总结(121+122+123+188+309+901+714)

    题目1----121. 买卖股票的最佳时机I: 链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/ 给定一个数组, ...

  3. leetcode 121 122 123 . Best Time to Buy and Sell Stock

    121题目描述: 解题:记录浏览过的天中最低的价格,并不断更新可能的最大收益,只允许买卖一次的动态规划思想. class Solution { public: int maxProfit(vector ...

  4. LeetCode No.121,122,123

    No.121 MaxProfit 买卖股票的最佳时机 题目 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你 ...

  5. 关于股票最佳买卖时机的lintcode代码

    class Solution {public:    /**     * @param prices: Given an integer array     * @return: Maximum pr ...

  6. LeetCode(123):买卖股票的最佳时机 III

    Hard! 题目描述: 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你最多可以完成 两笔 交易. 注意: 你不能同时参与多笔交易(你必 ...

  7. [LeetCode] Best Time to Buy and Sell Stock with Cooldown 买股票的最佳时间含冷冻期

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  8. [LeetCode] 121. Best Time to Buy and Sell Stock 买卖股票的最佳时间

    Say you have an array for which the ith element is the price of a given stock on day i. If you were ...

  9. [LeetCode] 122. Best Time to Buy and Sell Stock II 买卖股票的最佳时间 II

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

随机推荐

  1. Java 中(静态)变量、(静态)代码块的执行顺序

    Java 中(静态)变量.(静态)代码块的执行顺序 非原创 本文讨论 Java 中(静态)变量.(静态)代码块的执行顺序 首先创建 3 个类 1.Foo 类 public class Foo { pu ...

  2. 【centos 7】搭FTP服务和web访问

    步骤:安装 vsftpd-->增加用户-->配置vsftpd和用户权限 -->配置iptables 安装httpd,开放http访问 /var/tmp/user1下目录 1.安装和用 ...

  3. PHPStorm设置调试

    先下载PHP扩展Xdebug https://xdebug.org, 可以复制自己的phpinfo粘贴到https://xdebug.org/wizard.php中, 会生成需要下载的版本, php. ...

  4. Flask请求上下文源码讲解,简单的群聊单聊web

    请求上下文流程图 群聊html代码 <!DOCTYPE html> <html lang="en"> <head> <meta chars ...

  5. hdu 4284 状态压缩dp

    题意: 有N 个点的无向图,要去其中 h个地点做事,做事需要先办理护照,之后可以挣一定数量的钱,知道了一开始有的总钱数,和 一些城市之间           道路的花费,问可不可以在 指定的 h 个城 ...

  6. DML、DDL、DCL是什么?

    一.DML DML(data manipulation language)数据操纵语言: 我们经常会用到的 INSERT.DELETE.UPDATE.SELECT语句. 主要用来对数据库的数据进行一些 ...

  7. c# -- 实现浏览功能(备忘)

    最近在做系统的时候,要实现浏览功能,但是由于本人记性一般,每次写完就忘,所以还是写篇随笔,备忘一下,方便以后查看@_@# 实现功能大概如下: 按钮1:点击浏览按钮后,选择文件(类型为.txt),默认位 ...

  8. python开发_counter()

    在python的API中,提到了Counter,它具有统计的功能 下面是我做的demo: 1.统计自定义字符串中每个字符出现的次数 2.读取一个文件,把文件中的内容转化为字符串,统计该字符串中每个字符 ...

  9. VK Cup 2016 - Round 1 (Div. 2 Edition) C. Bear and Forgotten Tree 3 构造

    C. Bear and Forgotten Tree 3 题目连接: http://www.codeforces.com/contest/658/problem/C Description A tre ...

  10. uoj 67 新年的毒瘤 tarjan求割点

    #67. 新年的毒瘤 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/67 Description 辞旧迎新之际 ...