小白刷LeetCode拒绝暴力解法Day1

浅聊一下

作为一名小白,在leetCode刷题数已经达到了三位数,但是在我刷过的大部分题目中,都是使用的暴力解法,多层循环遍历等等...真的是有受够了自己


今天开始,我决定远离暴力解法,学习一下高端烧脑并且优雅的解法( ఠൠఠ )ノ

LeetCode:买卖股票的最佳时机

我们先来看题目:

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0

换做昨天的我估计在想,这这这,简单的不能再简单了,直接双层循环我就给他解决了...

但是今天,我选择用动态规划和贪心来完成这道题

动态规划

我们来看题目最后想要的结果是什么

=>返回你可以从这笔交易中获取的最大利润

注意 最大 这两个字,一般提到最大,我们就要想到动态规划,我们得用动态规划把这题干掉

那动态规划是怎么思考的呢?

  • 自顶而下

    我们要让最后的结果为最优解,自然要让前面的每一步都是最优解,带入题目

    我可以选择今天卖股票,也可以选择昨天卖股票,在今天以前,我们昨天卖掉股票所得的利润是最大的,于是我该和今天比较,如果今天卖的比昨天更多,那么我就今天把股票卖了...

  • 状态转移方程

    根据我们自顶向下的思想,我们可以列出状态转移方程

dp[i] = Math.max(dp[i-1],prices[i]-min)

dp[i]代表第i天卖出股票获利的最大值,如果第i天卖出的利润比dp[i-1]大,那么我们获得的最大利润就为dp[i],并且我们知道,在第一天买入股票之后当天是不能卖出股票的,所以

dp[0] = 0

js 复制代码
var maxProfit = function(prices) {
    const dp = new Array(prices.length).fill(0)
    let min = prices[0]
    for(let i = 1;i<prices.length;i++){
        min = Math.min(prices[i],min)
        dp[i] = Math.max(dp[i-1],prices[i]-min)
    }
    return dp[prices.length-1]
};

我们使用一个数组 dp 来保存每天卖出股票能够获得的最大利润。数组 dp 的长度与股票价格数组 prices 的长度相同。数组 dp 中的每个元素 dp[i] 表示在第 i 天卖出股票能够获得的最大利润。初始值都为0。

然后,我们从数组的第二个元素开始遍历(i = 1),对于每个元素 prices[i],我们进行以下操作:

  1. 计算在前 i-1 天中能够获得的最小买入价格 min。我们使用 Math.min(prices[i],min) 来更新最小买入价格 minprices[i] 表示当前的股票价格,如果这个价格比当前的最小买入价格 min 小,就更新最小买入价格为这个值。
  2. 计算在第 i 天卖出股票能够获得的最大利润。我们使用 Math.max(dp[i-1], prices[i]-min) 来更新数组 dp 中的元素。dp[i-1] 表示在前 i-1 天中获得的最大利润,因为我们不能在同一天既买入又卖出股票。所以,在第 i 天卖出股票的最大利润为 prices[i]-min,即当前股票价格减去前 i-1 天中的最小买入价格。然后,我们使用 Math.max 函数来比较 dp[i-1]prices[i]-min,取其中的较大值作为 dp[i] 的值。

通过遍历完整个数组,我们得到了最大利润。最后,我们返回 dp[prices.length-1] 作为函数的结果。

贪心

我们再来用贪心解决这道题

什么是贪心?就是我很贪心,总是想得到最多的东西...总是做出在当前看来是最好的选择 不从整体最优上加以考虑 算法得到的是局部最优解。

  • 在每一个价格上升的时刻,我们选择将股票卖出以获取最大利润;而在价格下降或持平的时候,我们选择保持最低买入价格。通过这样的策略,我们能够在一次遍历中找到最大利润,而不需要进行多次交易。
js 复制代码
var maxProfit = function(prices) {
   let min = prices[0]
   let profit = 0
   for(let i = 1;i<prices.length;i++){
    if(prices[i] > prices[i-1]){
        profit = Math.max(prices[i]-min,profit)
    }else{
        min = Math.min(prices[i],min)
    }    
   } 
   return profit
};

首先,我们初始化两个变量 minprofitmin 用于记录当前遍历到的最低买入价格,profit 用于记录当前的最大利润,初始值都为0。

然后,我们从数组的第二个元素开始遍历(i = 1),对于每个元素 prices[i],我们进行以下操作:

  1. 如果当前价格 prices[i] 大于前一个价格 prices[i-1],说明股票价格上升了。此时我们可以考虑将其卖出,并计算当前的利润。我们使用 Math.max(prices[i]-min, profit) 来更新当前的最大利润。prices[i]-min 表示将当前股票卖出后的利润,如果这个利润比当前的最大利润 profit 大,就更新最大利润为这个值。
  2. 如果当前价格 prices[i] 小于等于前一个价格 prices[i-1],说明股票价格下降了或者持平了。此时我们需要考虑是否要更新最低买入价格 min。我们使用 Math.min(prices[i], min) 来更新最低买入价格。prices[i] 表示当前的股票价格,如果这个价格比当前的最低买入价格 min 小,就更新最低买入价格为这个值。

通过遍历完整个数组,我们得到了最大利润。最后,我们返回最大利润作为函数的结果。

下班

想当聪明人的第一天完美结束...今天就写到这里吧!对了,最近掘金大大在搞年度优秀创作者投票活动,要是掘友们觉得小弟的文章让您有所收获,就给我投上一票吧!!!

相关推荐
阿伟来咯~13 分钟前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端18 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱21 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
sjsjs1122 分钟前
【数据结构-合法括号字符串】【hard】【拼多多面试题】力扣32. 最长有效括号
数据结构·leetcode
guai_guai_guai30 分钟前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨31 分钟前
在JS中, 0 == [0] 吗
开发语言·javascript
独行soc2 小时前
#渗透测试#SRC漏洞挖掘#深入挖掘XSS漏洞02之测试流程
web安全·面试·渗透测试·xss·漏洞挖掘·1024程序员节
咕咕吖2 小时前
对称二叉树(力扣101)
算法·leetcode·职场和发展
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试