代码随想录算法训练营第25天|134. 加油站、135. 分发糖果、860.柠檬水找零、406. 根据身高重建队列
LeetCode134
2025-02-25 18:34:10 星期二
题目描述:力扣134
文档讲解:代码随想录(programmercarl)134. 加油站
视频讲解:《代码随想录》算法视频公开课:贪心算法,得这么加油才能跑完全程!LeetCode :134.加油站
代码随想录视频内容简记
该题贪心的局部最优就是到当前站为止,剩余油量减去消耗油量的总和一旦小于0,说明不够走到下一站,那么直接从下一站开始作为起始点。全局最优就是这样可以能够走完一圈的起始点
注意:
如果给的gas和cost可以支持小车走完一圈,那么中间不管有几个负数,都必须跳过去,直到没有负数为止,因为一旦在负数之前开始走,那么收集到足够的油量,就一定有可能走不完。
另外就是这个做法和24买卖股票Ⅱ很像,只不过24是让返回最后获得的最大利润
LeetCode测试
点击查看代码
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int curSum = 0;
int totSum = 0;
int start = 0;
for (int i = 0; i < gas.size(); i++) {
totSum += gas[i] - cost[i];
}
if (totSum < 0) return -1;
for (int i = 0; i < gas.size(); i++) {
curSum += gas[i] - cost[i];
if (curSum < 0) {
curSum = 0;
start = i + 1;
}
}
return start;
}
};
LeetCode135
题目描述:力扣135
文档讲解:代码随想录(programmercarl)135. 分发糖果
视频讲解:《代码随想录》算法视频公开课:贪心算法,两者兼顾很容易顾此失彼!LeetCode:135.分发糖果
代码随想录视频内容简记
刚开始这个题是干啥的都没有读懂,后面看了一边视频才明白。给孩子分发糖果的上限是不限制的,这也是题目为什么说“相邻两个孩子评分更高的孩子会获得更多的糖果”。
这个题的要点就是涉及到了双向的比较,处理这种题目,一定是先从一边开始比较,再从一边开始比较。
本题的局部最优策略就是只给评分高的孩子多加一个糖果,全局最优就是可以分发最少的糖果
梳理
-
右孩子比左孩子评分高。从前向后遍历
-
左孩子比右孩子评分高。从后向前遍历
-
对candy数组中的值取最大,因为要必须两种情况都满足
大致代码内容
这里有一个细节需要注意,那就是在定义candy的时候必须给他赋好值vector<int> candy(ratings.size(), 1);
,要不然会报操作空指针的错
LeetCode测试
点击查看代码
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> candy(ratings.size(), 1);
int result = 0;
for (int i = 1; i < ratings.size(); i++) {
if (ratings[i] > ratings[i - 1]) candy[i] = candy[i - 1] + 1;
}
for (int i = ratings.size() - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1]) candy[i] = max(candy[i + 1] + 1, candy[i]);
}
for (int i = 0; i < candy.size(); i++) {
result += candy[i];
}
return result;
}
};
LeetCode860
题目描述:力扣860
文档讲解:代码随想录(programmercarl)860.柠檬水找零
视频讲解:《代码随想录》算法视频公开课:贪心算法,看上去复杂,其实逻辑都是固定的!LeetCode:860.柠檬水找零
代码随想录视频内容简记
这道题的解题思路就是针对每种钱,列处对应的找零数即可。
-
bills为5,不用找零
-
bills为10,找零5元
-
bills为20,找零15元。具体可以分成两种情况,第一种是10+5,第二种是5+5+5,这里贪心策略就是优先选择10+5的类型,可以省出来5元给bills为10的账单用,更通用一些
LeetCode测试
这个在实际代码编写的时候,还要多注意形成思路
点击查看代码
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int five = 0, ten = 0, twenty = 0;
for (int i = 0; i < bills.size(); i++) {
if (bills[i] == 5) five++;
else if (bills[i] == 10) {
if (five == 0) return false;
else {
ten++;
five--;
}
}
else if (bills[i] == 20) {
// 确定优先的情况一
if (ten > 0 && five > 0) {
ten--;
five--;
twenty++;
}// 确定情况二
else if (five >= 3) {
five -= 3;
twenty++;
}
else {
return false;
}
}
}
return true;
}
};
LeetCode406
题目描述:力扣406
文档讲解:代码随想录(programmercarl)406.根据身高重建队列
视频讲解:《代码随想录》算法视频公开课:贪心算法,不要两边一起贪,会顾此失彼 | LeetCode:406.根据身高重建队列
代码随想录视频内容简记
这道题的大题思路就是,按照题目中给出的people数组对其进行排序,先对身高h从大到小排序,之后按照people数组中的k进行排序,然后对其进行插入。
这道题目的核心要点就是要先对一个方向(或者顺序)进行操作,之后再对另一个方向(或者顺序)进行操作,是135分发糖果的思路延伸
LeetCode测试
这里注意,这样的写法是建立了一个数组进行操作,k哥那里还有链表的版本
点击查看代码
class Solution {
private:
static bool cmp(vector<int> a, vector<int> b) {
if (a[0] == b[0]) return a[1] < b[1];
return a[0] > b[0];
}
public:
vector<vector<int>> result;
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
sort(people.begin(), people.end(), cmp);
for (int i = 0; i < people.size(); i++) {
result.insert(result.begin() + people[i][1], people[i]);
}
return result;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构