加油站 leetcode 134
解法一:暴力解法for循环嵌套while循环
for循环适合模拟从头到尾的遍历,而while循环适合模拟环形遍历
index=(i+1)%gas,size();模拟一个新的索引确保其在gas数组大小范围内。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
for(int i=0;i<gas.size();i++){
int rest=gas[i]-cost[i];
int index=(i+1)%gas.size();
while(rest>0&&index!=i){
rest+=gas[index]-cost[index];
index=(index+1)%gas.size();
}
if(rest>=0&&index==i) return i;
}
return -1;
}
};
解法二:贪心算法
算出到达每一站的剩余油量,for循环遍历每个站点,一旦到达当前站点剩余油量小于0则记录起始位置为i+1,并清空剩余油量继续遍历。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int curSum=0,tatalSum=0,start=0;
for(int i=0;i<gas.size();i++){
curSum+=gas[i]-cost[i];
tatalSum+=gas[i]-cost[i];
if(curSum<0){
start=i+1;
curSum=0;
}
}
if(tatalSum<0) return -1;
return start;
}
};
分发糖果 leetcode 135
第一种情况,右边孩子评分大于左边孩子,从前向后遍历,然后考虑左边孩子评分大于右边孩子的情况,从后向前遍历,取两次情况分发糖果的最大值。
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> candY(ratings.size(),1);
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]);
}
int sum=0;
for(int i=0;i<candY.size();i++){
sum+=candY[i];
}
return sum;
}
};
总结
有两边一起比较的题目,先确定一边再确定另一边!
柠檬水找零 leetcode 860
一共三种情况,收到5、10、20分别记录(20不用记录因为不会用来找零)。收到20优先使用10找零,没有10再用三张5。
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int five=0,ten=0;
for(int i=0;i<bills.size();i++){
if(bills[i]==5) five++;
if(bills[i]==10){
ten++;
five--;
if(five<0) return false;
}
if(bills[i]==20){
if(five>0&&ten>0){
five--;
ten--;
}else if(five>=3){
five-=3;
}else return false;
}
}
return true;
}
};
根据身高重建队列 leetcode 406
先根据身高从大到小排序(如果身高大小相同就按前面有几个人比自身高的数量从小到大排序),再根据前面有几个人比自身高就插入到队列对应索引位置。
解法一:使用vector(会超时)
class Solution {
public:
static bool cmp(const vector<int>&a,const 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>> queue;
for(int i=0;i<people.size();i++){
int position=people[i][1];
people.insert(people.begin()+position,people[i]);
}
return queue;
}
};
C++中vector(可以理解是一个动态数组,底层是普通数组实现的)如果插入元素大于预先普通数组大小,vector底部会有一个扩容的操作,即申请两倍于原先普通数组的大小,然后把数据拷贝到另一个更大的数组上。
所以使用vector(动态数组)来insert,是费时的,插入再拷贝的话,单纯一个插入的操作就是O(n^2)了,甚至可能拷贝好几次,就不止O(n^2)了。
解法二:使用list(其底层为链表)
lass Solution {
public:
static bool cmp(const vector<int>& a,const 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) {
list<vector<int>> que;
sort(people.begin(),people.end(),cmp);
for(int i=0;i<people.size();i++){
int position=people[i][1];
list<vector<int>>::iterator it=que.begin();
//auto it=que.begin();
while(position--){
it++;
}
que.insert(it,people[i]);
}
return vector<vector<int>>(que.begin(),que.end());
}
};