其他分享
首页 > 其他分享> > 股票最大收益_1

股票最大收益_1

作者:互联网

leetcode 剑指offer63

degree:mid

description:

假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?

examples

示例 1:

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

示例 2:

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

 

限制:

0 <= 数组长度 <= 10^5

自己的解题过程:

想要把数组升序排序,建立值和原始序号的map;然后运用两个循环,外循环从第一个元素开始递增到最后一个,内循环从最后一个递减到当前最小,然后内循环当前最大的和外循环当前最小的,如果他们的index不“冲突”,则可以实现

设共有 nnn 天,第 aaa 天买,第 bbb 天卖,则需保证 a<ba < ba<b ;可推出交易方案数共有:

\((n−1)+(n−2)+⋯+2+1=n(n−1)/2(n - 1) + (n - 2) + \cdots + 2 + 1 = n(n - 1) / 2 (n−1)+(n−2)+⋯+2+1=n(n−1)/2\)

自己的这种想法的时间复杂度还是 o(n*2) ,甚至暴力法还没有写的很简单:

解决方案

我们需要找出给定数组中两个数字之间的最大差值(即,最大利润)。此外,第二个数字(卖出价格)必须大于第一个数字(买入价格)。

形式上,对于每组 i 和 j(其中 j>i)我们需要找出

\[max⁡(prices[j]−prices[i]) \]

然后官方的暴力法:

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

实际上,这点可以看出自己饶了很大的圈子,虽然最后程序调试成功了,但是从复杂度上来说是很差的程序。一开始自己想到了动态规划,但是由于一开始的出发点就是从程序能不能运行的角度去思考的,没有把条件判断总结出来,实际上这道题可以从很通俗的角度思考,但是本质还是动态规划dp。经过参考大佬的思路后,下面从两个角度分析这道题:

[1]

算法:

假设给定的数组为:[7, 1, 5, 3, 6, 4]

如果我们在图表上绘制给定数组中的数字,我们将会得到:

Profit Graph

我们来假设自己来购买股票。随着时间的推移,每天我们都可以选择出售股票与否。那么,假设在第 i 天,如果我们要在今天卖股票,那么我们能赚多少钱呢?

显然,如果我们真的在买卖股票,我们肯定会想:如果我是在历史最低点买的股票就好了!太好了,在题目中,我们只要用一个变量记录一个历史最低价格 minprice,我们就可以假设自己的股票是在那天买的。那么我们在第 i 天卖出股票能得到的利润就是 prices[i] - minprice

因此,我们只需要遍历价格数组一遍,记录历史最低点,然后在每一天考虑这么一个问题:如果我是在历史最低点买进的,那么我今天卖出能赚多少钱?当考虑完所有天数之时,我们就得到了最好的答案。

这里和自己想法的不同是:

不是去寻找所有天数中最低价格,(我这里想法的原因就是开头的那种想法,实际上:

我感觉算法到目前为止,很多抽象的,共性的大方向上的思考方法都已经被总结出来了,如果从时间复杂度上,自己要从更优的思考方法上着手,因为那些低时间复杂度的方法都是一种形而上的思想,是为了特定的条件而被思考和总结出来的,以后要多学习!

),而是考虑前 \(i\) 天的最低价格,这也是为什么前面说这道题的思路实际上是 DP 的原因

下面解释如何从动态规划的角度考虑:

[2]

动态规划解析:

前i日最大利润=max⁡(前(i−1)日最大利润,第i日价格−前i日最低价格)

\(dp[i]=max⁡(dp[i−1],prices[i]−min⁡(prices[0:i]))\)

(这个dp方程不仅考虑了前一天的,还有前 \(i\) 天的信息!!)

初始状态: dp[0]=0,即首日利润为 000 ;
返回值: dp[n−1],其中 n 为 dp 列表长度。

int maxProfit(vector<int>& prices) {
    int inf = 1e9;
    int minprice = inf, maxprofit = 0;
    for (int price: prices) {
        minprice = min(price, minprice);
        maxprofit = max(maxprofit, price - minprice);
    }
    return maxprofit;
}
}

---------总结到此结束

标签:最大,int,股票,收益,prices,minprice,dp,利润
来源: https://www.cnblogs.com/the-only-flash/p/14468300.html