听风是风

学或不学,知识都在那里,只增不减。

导航

JS leetcode 买卖股票的最佳时机 题解分析,我离职了。

壹 ❀ 引

昨天下班后,还是找经理提出了辞职,没有犹豫的裸辞,今天与人事的对话不小心被后台的同事听到,一下在公司传开了,下午我与同事们多人对线,被他们的消息轰炸....没错,我真的要走了。

因为什么原因呢?公司技术框架过于落后(angularjs1.6,不允许使用ES6等),很长时间我都很焦虑,担心自己再待下去是否会被这个行业淘汰,在过去的时间也学了一些东西,但都没法在工作中实践,以及待遇等等问题萦绕于心,才出此决策。

在与猎头的沟通中对方也是建议我先待着看看,不推荐裸辞,毕竟疫情影响行情不容乐观。我说如果当下处境良好我定会观望,只是深处温室之中越久,自己反而越害怕离职,涅槃重生还需经历烈火考验,比起骑驴找马,我还是更擅长破釜沉舟一点,祝自己好运。

还有一个月的工作交接期,顺便复盘自己的工作经历,还要复习,刷题,学习vue等等,压力巨大。不过既然是自己的决定,那就努力做到最好就好了。当然,后续面试我也会不断更新相关面试经历,多总结多积累,总没坏处。

好了,说了这么多,来看看今天的题目吧,题目来自121. 买卖股票的最佳时机,题目描述如下:

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

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

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

示例 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。

让我们简单分析题目,尝试解决它。

贰 ❀ 题解分析

其实当我看到[7,1,5,3,6,4]的例子,我第一反应也是为啥不是7-1=6,其实在题目的注意已经说明,我们在卖出股票时,必须得先买入,想要赚的多,一定是在历史最低价买入,在历史最高价卖出。注意,这个历史最低并不是数组中最小值,比如[3,5,1,2]这个例子,虽然我们在1买入最低,但后面价格只有2,利润反而不如3买入后5卖出。

我们需要理清的一点是,比如在第i天卖出,那么一定是在i-1天中最小的价格买入,因为得先买才能后卖,所以最笨的做法就是使用双循环,用尝试算出每一个i天与之前(i-1,i-2...)的差价,再找出其中最大的一个值即可,比如:

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
    // 因为如果没有利润就是0,这里初始化
    let maxProfit = 0;
    for (let i = 0; i < prices.length; i++) {
        // 注意,这里的j从i+1开始
        for (j = i + 1; j < prices.length; j++) {
            let profit = prices[j] - prices[i];
            // 不断用当前利润和历史最大利润比较,如果更大就替换maxProfit
            if (profit > maxProfit) {
                maxProfit = profit;
            };
        };
    };
    return maxProfit;
};

很简单也非常好懂,但是我们也清楚,这个耗时太久,只要价格数据越大,我们查询代价就越大。那么有没有更好的做法呢?当然有。

其实找到最大利润,其实无非就是找到历史最低价格,但事实上我们不知道哪个是最低价,没关系,我们可以先假设第一天是最低,遍历数组的同时,让当前价格与历史最低比较,如果更低,那自然要更新历史最低价了。

更新了最低价之后呢?当然是用当前价格减去历史最低价求出利润,并与历史比较,始终记录较大的利润即可,直到遍历结束,返回最终的价格不就是最大的利润了,比如:

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
    let maxProfit = 0,
        // 假设0位价格为历史最低
        minPrice = prices[0];
    // i从1开始
    for (let i = 1; i < prices.length; i++) {
        // 如果后续价格比历史更低,更新最低价
        minPrice = Math.min(minPrice, prices[i]);
        // 计算利润,找出最大利润
        maxProfit = Math.max(maxProfit, prices[i] - minPrice);
    };
    return maxProfit;
};

我们来以[7,6,4,3,1]这个例子来看,由于价格越来越低,最低价格也一直随便遍历变化,导致利润计算始终为0,而对于第一个例子,一旦锁定了一个历史低价,后续要做的就是不断与之后的价格比较,从中找到最大利润。

这个思路也叫动态规划,虽然我现在也不是很理解- - ,看后续做题能否积累,那么本文就到这里就结束了。

posted on 2020-06-30 23:48  听风是风  阅读(885)  评论(2编辑  收藏  举报