Leetcode 121.买卖股票的最佳时机

Leetcode 121.买卖股票的最佳时机

  • 前言
  • 一、题目描述与分析
  • 二、题解以及代码
    • 解法1:暴力法
    • 解法2:动态规划
    • 解法3:贪心算法
  • 总结

前言

在本篇题解中,我们将解决力扣第 121 题,该题要求在给定的股票价格数组中找到最大的利润,允许完成一笔交易,即买入一支股票并卖出一支股票。我们将提供三种不同的解决方法,并分析它们的时间复杂度和空间复杂度。加油,刷题使我快乐!

一、题目描述与分析

给定一个数组 prices,其中 prices[i] 是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入一支股票并卖出一支股票),请计算你能获取的最大利润。注意,你不能在买入股票前卖出股票。

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

题目描述:
这道题目要求找出最大的利润,可以在一天内买入然后在未来的某一天卖出。为了找到最大利润,我们可以尝试不同的策略,但需要注意买入必须在卖出之前。

二、题解以及代码

博主对于题目的分析以及解决方法

解法1:暴力法

思路:
最简单的方法是对于每一天,都尝试在该天买入股票,并在之后的每一天卖出股票,计算利润,然后选择最大的利润。

public int maxProfit(int[] prices) {
    int maxProfit = 0;
    for (int i = 0; i < prices.length; i++) {
        for (int j = i + 1; j < prices.length; j++) {
            int profit = prices[j] - prices[i];
            if (profit > maxProfit) {
                maxProfit = profit;
            }
        }
    }
    return maxProfit;
}

时间复杂度: O(n^2),需要两层循环遍历所有可能的买入和卖出日期。

空间复杂度: O(1),只需要常数级别的额外空间。

注意:这个方法在处理大量数据时会超时,所以不推荐大家使用这种方式。

解法2:动态规划

思路:

使用动态规划来解决这个问题,维护一个数组 dp,其中 dp[i] 表示第 i 天卖出股票所能获得的最大利润。我们需要遍历股票价格数组,更新 dp 数组的值。

dp[0] 初始化为 0,因为第一天无法卖出。
对于每一天 i,计算 dp[i] 的值,可以选择在第 i 天卖出,也可以选择不卖出。
如果选择在第 i 天卖出,那么 dp[i] 就等于第 i 天的价格减去前面若干天的最低价格(即 minPrice)。
如果选择不卖出,那么 dp[i] 就等于 dp[i-1]
最终返回 dp 数组中的最大值即可。

public int maxProfit(int[] prices) {
    if (prices == null || prices.length == 0) {
        return 0;
    }
    
    int minPrice = prices[0];
    int[] dp = new int[prices.length];
    
    for (int i = 1; i < prices.length; i++) {
        minPrice = Math.min(minPrice, prices[i]);
        dp[i] = Math.max(dp[i - 1], prices[i] - minPrice);
    }
    
    return dp[prices.length - 1];
}

时间复杂度: O(n),需要遍历股票价格数组一次。

空间复杂度: O(n),需要额外的数组 dp 来存储中间结果。

解法3:贪心算法

思路:

贪心算法的核心思想是维护两个变量,一个是最小价格 minPrice,一个是最大利润 maxProfit。在遍历股票价格数组的过程中,不断更新这两个变量的值。

初始化 minPrice 为第一天的价格,maxProfit 为 0。
遍历股票价格数组,对于每一天的价格:
如果当前价格小于 minPrice,更新 minPrice。
否则,计算当前价格与 minPrice 之间的差值,如果差值大于 maxProfit,则更新 maxProfit。
最终返回 maxProfit 即可。

public int maxProfit(int[] prices) {
    int minPrice = Integer.MAX_VALUE;
    int maxProfit = 0;
    
    for (int i = 0; i < prices.length; i++) {
        if (prices[i] < minPrice) {
            minPrice = prices[i];
        } else if (prices[i] - minPrice > maxProfit) {
            maxProfit = prices[i] - minPrice;
        }
    }
    
    return maxProfit;
}

时间复杂度: O(n),需要遍历股票价格数组一次。

空间复杂度: O(1),只需要常数级别的额外空间。

总结

通过这篇题解,我们学习了解决力扣第 121 题的三种不同方法:暴力法、动态规划和贪心算法。这些方法分别具有不同的时间和空间复杂度,但都能有效地解决这个问题。选择合适的方法取决于问题的实际要求和输入数据的规模。希望这篇题解对你有所帮助!
第一个方法是我先想到的思路,也不出意外地超时了,至于我写在这里只是告诉大家暴力解法不可取,第二个和第三个方法是可以过的,时间复杂度也比第一个更好。如果有什么问题可以与博主交流。

你可能感兴趣的:(刷题计划,java,算法)