134. 加油站
134. 加油站
剩余油量rest
小于0
,不能到达下一个加油站;更新下一个加油站为起始加油站;路过加油站数量为gas.size()
时,说明可以绕环路行驶一周,返回起始加油站的下标
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int count = 0; // 路过加油站的个数
int sum = 0; // 统计剩余油量
int len = gas.size();
// 起点不确定,两倍长度判断是否可以绕一圈
for (int i = 0; i < 2 * len; ++i) {
sum += gas[i%len] - cost[i%len];
count++;
if (sum < 0) { //剩余油量小于0,无法到达下一个加油站
sum = 0;
count = 0;
}
if (count == len) {
return (i + 1) % len;
}
}
return -1;
}
};
135. 分发糖果
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> candyVec(ratings.size(), 1);
// 从前向后遍历,比较右边孩子评分比左边大的情况。
for (int i = 1; i < ratings.size(); i++) {
if (ratings[i] > ratings[i - 1]){
candyVec[i] = candyVec[i - 1] + 1;
}
}
// 从后向前遍历,比较左边孩子评分比右边大的情况
for (int i = ratings.size() - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1] ) {
candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1);
}
}
// 统计结果
int sum = 0;
for (int i = 0; i < candyVec.size(); i++){
sum += candyVec[i];
}
return sum;
}
};
失败的思路:考虑给评分极小值的孩子分发一颗糖果,但是两个极小值之间的区间不一定是单调的;
860.柠檬水找零
860.柠檬水找零
顾客付钱有三种情况,如下:
1、支付 5 美元,不用找零,直接收下,增加一张 5 美元;
2、支付 10美元,找零一张 5 美元,增加一张 10 美元;
3、支付 20 美元,优先找零一张 10 美元和 5 美元;如果不够,就找零三张 5 美元;同时增加 20 美元;
可以根据上面的情况直接模拟
对于支付 5 美元和支付 10 美元,找零请况是固定的;
因为10 美元只能给 20 美元找零;5 美元可以给 10 美元和 20 美元找零;对于支付 20 美元,就要优先找零 10 美元;
局部最优:顾客支付 20 美元,优先找零一张 10 美元和 5 美元;如果不够,就找零三张 5 美元
全局最优:完成全部账单的找零
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int five = 0, ten = 0; // 零钱币值为 5 美元和 10 美元的个数
for (int i = 0; i < bills.size(); i++) {
if (bills[i] == 5) { // 顾客付 5 美元, 不用找零
five++;
}
else if (bills[i] == 10) {
// 顾客付 10 美元, 找零一张 5 美元
if (five >= 1) {
five--;
ten++;
}else {
return false;
}
} else if (bills[i] == 20) {
if (ten >= 1 && five >= 1) {
// 顾客付 20 美元, 找零一张 10 美元和 5 美元
ten--;
five--;
} else if (five >= 3) {
// 顾客付 20 美元, 找零三张 5 美元
five -= 3;
} else {
return false;
}
}
}
return true;
}
};
406.根据身高重建队列
406.根据身高重建队列
局部最优:优先按身高高的people的k来插入。插入操作过后的people满足队列属性
全局最优:最后都做完插入操作,整个队列满足题目队列属性
按照身高由大到小排序后:
依次将每个人放入队列中,那么当我们放入第 i
个人时:
第 0,⋯,i−1
个人已经在队列中被安排了位置,他们只要站在第 i
个人的前面,就会对第 i
个人产生影响,因为他们都比第 i
个人高;
而第 i+1,⋯,n−1
个人还没有被放入队列中,并且他们无论站在哪里,对第 i
个人都没有任何影响,因为他们都比第 i
个人矮。
采用「插空」的方法,依次给每一个人在当前的队列中选择一个插入的位置。也就是说,当我们放入第 i 个人时,只需要将其插入队列中,使得他的前面恰好有 k
个人即可。
class Solution {
public:
static bool cmp(vector<int>& a, vector<int>& b) {
if (a[0] == b[0]){ // 身高相等,属性小的在前
return a[1] < b[1];
}
return a[0] > b[0]; // 身高不等,身高大的在前
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
// 身高从大到小排序
sort (people.begin(), people.end(), cmp);
vector<vector<int>> res;
for (int i = 0; i < people.size(); i++) {
int position = people[i][1];
res.insert(res.begin() + position, people[i]);
}
return res;
}
};