LeetCode刷题(四)-----数组-------easy部分(Java、C++)

LeetCode刷题(四)-----数组-------easy部分(Java、C++)

121. 买卖股票的最佳时机

给定一个数组,它的第i个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。

在这里插入图片描述
思路1:
方法一:暴力枚举
使用两个变量i和j,它们分别表示买进这支股票和卖出这支股票,枚举它们在价格数组上可能出现的所有位置。编码很简单,相信大家都会,写一个二重循环即可。
参考代码 1:
在这里插入图片描述
复杂度分析:
• 时间复杂度:O(N^2);
• 空间复杂度:O(1)
复杂度较高,提交到 LeetCode 以后排名稍微靠后。

方法二:针对暴力枚举的优化
我们发现:我们只关心之前(不包括现在)看到的最低股价,于是在遍历的过程中,记录下之前看到的最低股价,可以省去内层循环。
在这里插入图片描述
复杂度分析:
• 时间复杂度:O(N);
• 空间复杂度:O(1)。

思路2:
我们需要找出给定数组中两个数字之间的最大差值(即,最大利润)。此外,第二个数字(卖出价格)必须大于第一个数字(买入价格)。
形式上,对于每组 i 和 j(其中j>i)我们需要找出max(prices[j] - prices[i])。
方法一:暴力法
在这里插入图片描述
复杂度分析
在这里插入图片描述
方法二:一次遍历
算法
在这里插入图片描述
使我们感兴趣的点是上图中的峰和谷。我们需要找到最小的谷之后的最大的峰。
我们可以维持两个变量——minprice 和 maxprofit,它们分别对应迄今为止所得到的最小的谷值和最大的利润(卖出价格与最低价格之间的最大差值)。
在这里插入图片描述

我的:

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

作者:LeetCode
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-by-leetcode/
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/bao-li-mei-ju-dong-tai-gui-hua-chai-fen-si-xiang-b/
https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-by-leetcode/

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

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

在这里插入图片描述
题解思路:
思路一:
这道题其实是一个非常简单的将多个线段重叠然后算最终线段的长度问题。
在这里插入图片描述
参考:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/ji-bai-98gao-xiao-suan-fa-si-lu-pou-xi-mai-mai-gu-/

思路二:
贪心算法
这次题目同样是给出N天的价格,但是不同于上一题只买入卖出一次,这次可以买入卖出多次,求最大的收益。

看完题目之后,一脸懵,这个完全不同于上一题啊,这个难度还是简单的?咦,那一定是我没找到思路,难道又是贪心?

先捋清一下思路,买入肯定是找价格低的时候买入,卖出肯定是价格高的时候卖出,那么价格一路高涨的情况下,肯定是在最高价的时候卖出;那假如中间某一天价格稍微降低了一点点,然后又涨回去了,那我是应该在前面卖出,再重新买入,还是一直持有,等后面再卖出呢?

假如有以下四天的价格,分别是a,b,c,d,其中a < b, c < b, c < d, 其余的大小无所谓,那么在什么情况下,“买入,卖出,再买入,卖出”会比“买入,持有,持有,卖出”能得到更多收益呢?也就是什么情况下会有b-a+d-c>d -a呢?来来来,解一下上面的不等式,得到b>c,也就是说当b>c的时候,这不正就是我们最前面的假设条件吗?反过来说,我们不断的买入卖出就能得到更大的收益,当知道价格要降低的时候,就得卖出了!

通过判断趋势(两点的差值),有上涨的趋势【买】, 有下降的趋势【卖】
在这里插入图片描述在这里插入图片描述链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/q122-best-time-to-buy-and-sell-stock-ii-by-ronhou/
https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-ii-c-by-will-2-2/

思路三:
方法一:暴力法
这种情况下,我们只需要计算与所有可能的交易组合相对应的利润,并找出它们中的最大利润。
在这里插入图片描述复杂度分析
• 时间复杂度:O(nn),调用递归函数nn次。
• 空间复杂度:O(n),递归的深度为n。

方法二:峰谷法
算法
假设给定的数组为:[7, 1, 5, 3, 6, 4],如果我们在图表上绘制给定数组中的数字,我们将会得到:
在这里插入图片描述如果我们分析图表,那么我们的兴趣点是连续的峰和谷。
用数学语言描述为:
在这里插入图片描述
关键是我们需要考虑到紧跟谷的每一个峰值以最大化利润。如果我们试图跳过其中一个峰值来获取更多利润,那么我们最终将失去其中一笔交易中获得的利润,从而导致总利润的降低。

例如,在上述情况下,如果我们跳过 peaki和 valleyj试图通过考虑差异较大的点以获取更多的利润,获得的净利润总是会小与包含它们而获得的静利润,因为 C总是小于 A+B。
在这里插入图片描述复杂度分析
• 时间复杂度:O(n)。遍历一次。
• 空间复杂度:O(1)。需要常量的空间。

方法三:简单的一次遍历
算法
该解决方案遵循 方法二 的本身使用的逻辑,但有一些轻微的变化。在这种情况下,我们可以简单地继续在斜坡上爬升并持续增加从连续交易中获得的利润,而不是在谷之后寻找每个峰值。最后,我们将有效地使用峰值和谷值,但我们不需要跟踪峰值和谷值对应的成本以及最大利润,但我们可以直接继续增加数组的连续数字之间的差值,如果第二个数字大于第一个数字,我们获得的总和将是最大利润。这种方法将简化解决方案。
这个例子可以更清楚地展现上述情况:[1, 7, 2, 3, 6, 7, 6, 7]
与此数组对应的图形是:
在这里插入图片描述从上图中,我们可以观察到A+B+C的和等于差值D所对应的连续峰和谷的高度之差。
在这里插入图片描述链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/solution/mai-mai-gu-piao-de-zui-jia-shi-ji-ii-by-leetcode/
来源:力扣(LeetCode)
我的答案:

class Solution {
public:
    int maxProfit(vector<int>& prices)
    {
        int maxprofit = 0;
        for(int j=1;j<prices.size();j++)
        {
            if(prices[j-1]<prices[j])
                maxprofit=maxprofit+prices[j]-prices[j-1];
        }
        return maxprofit;
    }
};

发布了47 篇原创文章 · 获赞 21 · 访问量 7257

猜你喜欢

转载自blog.csdn.net/qq_18315295/article/details/102863167
今日推荐