代码随想录算法训练营
Day29 代码随想录算法训练营第 29 天 |LeetCode134. 加油站 LeetCode 135. 分发糖果 LeetCode860.柠檬水找零 LeetCode 406.根据身高重建队列
目录
前言
LeetCode134. 加油站
LeetCode 135. 分发糖果
LeetCode860.柠檬水找零
LeetCode 406.根据身高重建队列
一、LeetCode 134. 加油站
1.题目链接
2.思路
(1)如果总油量减去总的消耗大于等于0,那么一定可以走完
(2)也就是说,如果每个加油站剩下的油之和大于等于0,则一定可以走完
(3)
1)先假设从下标为0出发,累加剩余油量
2)如果cur小于0,那么[0,i]不可作为起点(会卡在里面)
3)以i+1为新的起点,清空cur
注意:
cur是从起点开始剩余油量的累加
total是总的剩余油量累加
3.题解
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int total = 0;
int cur = 0;
int start = 0;
vector<int> res;
for (int i = 0; i < gas.size(); i++) {
res.push_back(gas[i] - cost[i]);
cur += res[i];
total += res[i];
if (cur < 0) {
cur = 0;
start = i + 1;
}
}
if (total < 0)
return -1;
else
return start;
}
};
二、LeetCode 135. 分发糖果
1.题目链接
2.思路
(1)尽可能是2糖果总数少,所以相邻评分有差异的小孩多给或者少给1块
(2)为了避免出现负数,我们选择在评分低的小孩的糖数上进行增加获得评分高的小孩的糖数
最初每人给一块糖
(3)处理左侧小孩评分低于右侧小孩
1)从左向右遍历:
因为先是在评分低的孩子糖数的基础上进行增加,所需要先知道评分低的孩子–在左边
2)如果左侧小孩评分低于右侧小孩 ,右侧小孩糖数=左侧小孩糖数+1(如果当前的右侧小孩糖数>=左侧小孩糖数,则右侧小孩糖数不变)
(4)处理左侧小孩评分高于右侧小孩
1)从右向左遍历:
因为先是在评分低的孩子糖数的基础上进行增加,所需要先知道评分低的孩子–在右边
2)如果左侧小孩评分高于右侧小孩 ,左侧小孩糖数=右侧小孩糖数+1
(如果当前的左侧小孩糖数>=右侧小孩糖数,则左侧小孩糖数不变)
3.题解
class Solution {
public:
int candy(vector<int>& ratings) {
int sum = 0;
vector<int> res(ratings.size(), 1);
for (int i = 1; i < ratings.size(); i++) {
if (ratings[i] > ratings[i - 1])
res[i] = max(res[i], res[i - 1] + 1);
}
for (int i = ratings.size() - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1])
res[i] = max(res[i], res[i + 1] + 1);
}
for (int i = 0; i < ratings.size(); i++) {
sum += res[i];
}
return sum;
}
};
三、LeetCode860.柠檬水找零
1.题目链接
2.思路
(1)顾客支付5元:存入零钱(下标1对应10元,下标0对应5元)
(2)顾客支付10元:找零5元
如果没有5元—false
有五元,找零
(3)顾客支付15元:找零5元
如果没有5元—false
优先用10元找零,因为5元更宝贵
如果有十元,就用10+5找零
如果没有十元,就用5*3找零
3.题解
lass Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int change[2] = {0}; // 1----10yuan 0-------5yuan
for (int i = 0; i < bills.size(); i++) {
if (bills[i] == 5) {
change[0]++;
} else if (bills[i] == 10) {
if (change[0] == 0)
return 0;
else {
change[0]--;
change[1]++;
}
} else {
if (change[0] == 0)
return 0;
if (change[1] != 0) {
if (change[1] != 0) {
change[1]--;
change[0]--;
} else {
return 0;
}
} else {
if (change[0] >= 3) {
change[0] -= 3;
} else
return 0;
}
}
}
return 1;
}
};
四、LeetCode 406.根据身高重建队列
1.题目链接
2.思路
(1)有两个变量,身高h和前面高于此人或一样高的人数k
1)如果用k作为优先考虑的量,在排布以后还可能顺序不对
2)所以用h作为优先考虑的依据
(2)根据h进行排序,优先把身高高的人放进队列,这样每次考虑时,队列内的人都比现在考虑的人高,或者一样高,这样只需考虑此人的k
(3)用vector存答案速度慢,用链表存回更快
3.题解
数组存答案
class Solution {
public:
static bool cmp(vector<int> a,vector<int>b)
{
if(a[0]!=b[0])return a[0]>b[0];
else return a[1]<b[1];
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
vector <vector<int>>queue;
sort(people.begin(),people.end(),cmp);
for(int i=0;i<people.size();i++)
{
int pos=people[i][1];
queue.insert(queue.begin()+pos,people[i]);
}
return queue;
}
};
链表存答案
class Solution {
public:
static bool cmp(vector<int> a, vector<int> b) {
if (a[0] != b[0])
return a[0] > b[0];
else
return a[1] < b[1];
}
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
list<vector<int>> queue;
sort(people.begin(), people.end(), cmp);
std::list<vector<int>>::iterator it = queue.begin();
for (int i = 0; i < people.size(); i++) {
int pos = people[i][1];
std::list<vector<int>>::iterator it = queue.begin();
while (pos) {
it++;
pos--;
}
queue.insert(it, people[i]);
}
return vector<vector<int>>(queue.begin(), queue.end());
}
};