本文面向于了解前端面试算法且算法入门的同学
本题虽然属于简单题,但是也是前端面试考察最多的算法题之一,其中的动态规划的算法思想是面试官想要考察的
一般公司前端对于算法能力要求不高,除非是头部大厂,一般考动态规划都不会太难,考察到的难度会到中等的矩阵类问题
贪心/动态规划
动态规划
动态规划(Dynamic Programming,简称DP)是一种通过将原问题分解为相互重叠的子问题来求解问题的方法。它通常用于优化问题,其中问题的最优解可以通过递归地求解其子问题的最优解而得到。
动态规划的基本思想是将原问题分解为若干子问题,先求解子问题的最优解,然后将子问题的最优解组合起来得到原问题的最优解。为了避免重复计算子问题,动态规划使用一张表格(通常是二维数组)来存储已经计算过的子问题的解,从而避免重复计算,提高算法的效率。
动态规划通常适用于满足两个条件的问题:
- 最优子结构性质(Optimal Substructure): 问题的最优解可以通过子问题的最优解来构造。
- 重叠子问题(Overlapping Subproblems): 问题可以被分解为若干个子问题,这些子问题可能会被多次求解。
const maxProfit = function(price){
//每个dp[i]表示在该天的获利
const dp = new Array(price.length).fill(0)
let min = price[0]
for (let i = 1; i < price.length; i++) {
min=Math.min(min,price[i])
dp[i] =Math.max(price[i] -min,dp[i-1])
}
return dp [dp.length - 1]
}
let price = [7,1,5,3,6,4]
console.log(maxProfit(price))//结果为5
解析
- 先找到该问题的子问题:某一天i中买卖股票的最大获利值,就是从第一天开始到最后一天里,这段时间内最大的差值便是该天最大的获利值
- 处理子问题之间的叠加:后一天i-1的最大利润值,要么是在前段时间卖出得到的利润,要么就是在i-1当天卖出所得的利润值,这样也能推导出最后一天,也就是整段时间内的最大利润
- 实现:
- 创建一个状态数组dp来表示每天能够获得的最大利润dp[i]
- 通过一个变量min来存储当前遍历到的最小值,再每次计算以遍历的当天股票价格price[i]减去min的值(卖出所得的利润)如果比前一天获得的利润多,就执行dp[i]=price[i]-min,否则dp[i]=dp[i-1]
- 这样最后一天dp[dp.length]就能够表示这段时间内获得的最大利润
贪心
贪心算法是一种在每一步选择中都采取当前状态下最优的选择,从而希望以局部最优达到全局最优的算法。贪心算法的核心思想是通过局部最优的选择,逐步构建问题的解,以期望最终获得全局最优解。
本题也可以通过贪心算法将局部最优解构成全局最优解,其实和动态规划的解法类似。
//贪心算法
const maxProfit2 = function(price){
// 将两次的比较放在一个循环当中
let min = price[0]
let res = 0
for (let i = 1; i < price.length; i++) {
const element = price[i];
//通过两个变量来保存选中元素前面的最小值,和最大的差值
min = Math.min(min,price[i])
res = Math.max(res,price[i]-min)
}
return res
}
let price = [7,1,5,3,6,4]
console.log(maxProfit2(price));//结果5
解析
- 我们只需要找到两个数差值最大就行 这样我们需要双重for循环
- 我们转换一下思想,当遍历数组的时候在寻找最大元素的同时去寻找当前元素前的最小元素,这样在一个for循环内便可以实现找到符合先后条件两个最值
- 实现:通过两个外部变量min,res,当遍历数组每一项时,维护min始终是当前遍历的元素中最小的,res为min和每个元素的差值中的最大值,循环结束,res就是最大利润
总结
想要在面试当中脱颖而出,不仅需要做大量算法题,还需要积累算法知识与思想(质的提升) 所以刚入门的掘友们,在刷算法题的时候也需要去多思考其中的算法