贪心
leetcode 455 分饼干
该问题需要尽可能多地满足孩子的需求,并且每个孩子只能分配一块饼干。输入参数 g 和 s 分别代表孩子的需求和饼干的大小,任务是计算最多能够满足多少孩子的需求。
js
//暴力破解 逻辑 O(n^2)
//O(nlogN) 快排 归并排序 排序+双指针
//策略 双指针
var findContentChildren = function(g, s) {
g = g.sort((a,b)=>a-b)
s = s.sort((a,b)=>a-b)
let gi = 0
let sj = 0
let res = 0
while(gi<g.length&&sj<s.length){
if(s[sj]>=g[gi]){ //当下
gi++;
sj++;
res++;
}else{
sj++;
}
}
return res
}
console.log(findContentChildren([1,2], [1,2,3]));
这段代码使用了贪心算法解决该问题,其核心思想是每次都选择当前情况下的最优解,而不考虑未来的影响。具体实现步骤如下:
- 对孩子的需求和饼干的大小进行升序排序,方便后续比较大小。
- 定义两个指针 gi 和 sj,分别指向孩子的需求和饼干的大小数组的起始位置。
- 依次比较孩子的需求和饼干的大小,如果饼干的大小大于等于孩子的需求,则将该饼干分配给该孩子,同时将 gi 和 sj 指针都向后移动一位,并累加满足的孩子数量。
- 如果饼干的大小小于孩子的需求,则只将 sj 指针向后移动一位。
- 重复步骤 3 和 4,直到 gi 或 sj 超出数组的范围。
- 返回满足需求的孩子数量。
在该代码实现中,时间复杂度为 O(nlogn),其中 n 为孩子的需求和饼干的大小数组的长度。
动态规划
leetcode 198 打家劫舍
该问题描述了一排房屋,每个房屋内有一定数量的现金。相邻的房屋在同一晚上被闯入会触发警报系统,因此不能连续盗窃相邻的房屋。任务是计算在不触发警报的情况下,能够获得的最大金额。
js
var rob = function (nums) {
//没有状态转移方程不要动手
const dp=[] //最优子结构,O(n) 一维数组,缓存状态结果
dp[0] = 0
dp[1] = 0
for(let i=2;i<nums.length+2;i++){
dp[i] = Math.max(dp[i-2]+nums[i-2],dp[i-1])
}
return dp[dp.length-1]
}
console.log(robTo([1,2,3,1])); //最优
这段代码使用了动态规划的思想来解决该问题。动态规划通过定义状态转移方程,利用之前的计算结果来推导出当前的最优解。具体实现步骤如下:
- 定义一个一维数组
dp
,用于缓存状态结果,其中dp[i]
表示打劫前i
个房屋能够获得的最大金额。 - 初始化
dp[0]
和dp[1]
为 0,表示前 0 个和前 1 个房屋都无法打劫。 - 使用循环从第 2 个房屋开始遍历到最后一个房屋(即
i
从 2 取值到nums.length + 1
),并根据状态转移方程计算dp[i]
的值。 - 状态转移方程为
dp[i] = Math.max(dp[i-2] + nums[i-2], dp[i-1])
,表示在打劫第i
个房屋时有两种选择:打劫或不打劫。如果打劫第i
个房屋,则能获得的最大金额为dp[i-2] + nums[i-2]
;如果不打劫第i
个房屋,则能获得的最大金额为dp[i-1]
。取两者中较大的值作为dp[i]
的结果。 - 循环结束后,返回
dp[dp.length-1]
,即最后一个房屋处能够获得的最大金额。
在该代码实现中,时间复杂度为 O(n),其中 n 为房屋数量。因为只需遍历一次房屋数组,计算出每个位置的状态结果即可。
最值问题
在动态规划和贪心算法中,最值问题的解决方法取决于问题的特性。下面对这两种方法进行简要的分析:
-
动态规划:
- 适用情况:动态规划适用于具有最优子结构和重叠子问题特性的问题。当原问题的最优解可以通过子问题的最优解推导出,并且多个问题需要解决同一个子问题时,通常可以使用动态规划。
- 解决方式:动态规划通过将原问题分解成若干子问题,计算并存储子问题的解,然后利用之前计算得到的结果来推导当前问题的解。这种自底向上的推导过程可以避免重复计算,提高效率。
-
贪心算法:
- 适用情况:贪心算法适用于局部最优解独立且不需要推导出原问题的情况。在贪心算法中,每一步都选择当前状态下的最优解,而不考虑之前的状态或之后的影响。如果子问题之间不存在重叠,并且当前的最优选择不会影响后续步骤的选择,通常可以考虑使用贪心算法。
- 解决方式:贪心算法每一步都选择局部最优解,并且相信这些局部最优解能够推导出全局最优解。因为贪心算法不需要回溯或者推导子问题的解,所以在某些情况下可能会更加直观和简单。
综上所述,动态规划适用于具有最优子结构和重叠子问题特性的问题,而贪心算法适用于局部最优解独立且不需要推导出原问题的情况。在解决最值问题时,根据问题的特性选择合适的方法可以帮助我们更高效地解决问题。