LeetCode1700.无法吃午餐的学生数量
ques:
学校的自助午餐提供圆形和方形的三明治,分别用数字 0 和 1 表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。
餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个 栈 里,每一轮:
- 如果队列最前面的学生 喜欢 栈顶的三明治,那么会 拿走它 并离开队列。
- 否则,这名学生会 放弃这个三明治 并回到队列的尾部。
这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。
给你两个整数数组 students 和 sandwiches ,其中 sandwiches[i] 是栈里面第 i 个三明治的类型(i = 0 是栈的顶部), students[j] 是初始队列里第 j 名学生对三明治的喜好(j = 0 是队列的最开始位置)。请你返回无法吃午餐的学生数量。
ans:
循环有两个终止情况,一个是正常的循环,学生数被自减为0 了,另一种就是,一个栈顶的蛋糕,被队列里全部学生循环了个遍,也没有与之匹配的,自然就得结束了。但这不能就只设置循环count一个变量了,还要有个辅助循环变量i。
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
int countStudents(vector<int>& students, vector<int>& sandwiches) {
int count = students.size();
int i = 0;//当一个栈顶一直不变时候,根据学生数,作为循环判断的依据(一个栈顶最多不超过学生数次循环)
while(count>0)//两种情况,一种是学生数量为0,全部拿到了蛋糕
{
if(students[0]==sandwiches[0])
{
students.erase(students.begin());
sandwiches.erase(sandwiches.begin());
count--;
i = 0;//每次count数减1后需要将i重置为0
}
else
{
//i++;
if(++i>=count)
break;//两种情况,另一种是一个栈顶对应了学生数次的循环,该终止跳出循环了
students.push_back(students.front());
students.erase(students.begin());
}
}
if(count=students.size())
return count;
else
return 0;
}
};
summary:
我觉得最难的是循环结束条件的判断,我最开始没引入i变量,只用 int count = students.size();和while(count--)判断,提交一次发现了问题,比如在下面情况就会出现问题,循环只4次就终止了。

由于题目限制用vector实现,于是也浅浅回顾了下vector的用法,及常用函数,如erase、begin、push_back,front等等,需要用到时自行百度即可。特殊的如front函数返回的是引用:
front |
返回对向量中第一个元素的引用。 |
还有size与capacity的区别,当然这里是size啦,capacity是容器的大小,比如容器弹出元素时,size会减1,而capacity不会变化。
其中有些函数涉及到迭代器iterator的概念,这在一篇csdn博客上展现的尤为清晰,介绍了vector删除指定元素的三种方法:
值得注意的是,这里方法二用到的begin()函数返回的是一个迭代器,也就是相当于方法一中定义的那个迭代器,通过它可以访问首元素(或者直接用数组下标应该也是可以的?)
begin |
对该向量中第一个元素返回随机访问迭代器 |
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int>vec;//定义一个容器vec
for (int i = 0; i < 5; i++)//给该容器装进5个数
vec.push_back(i);
for (auto&v : vec)
cout << "没删除时容器的元素有:" << v << endl;
//方法1:利用迭代器定位某元素位置将其删掉
vector<int>::iterator iter = vec.begin() + 4;
vec.erase(iter);//删除该容器第5个位置的数
for (auto&v : vec)
cout << "第一次删除后容器的元素还有:" << v << endl;
//方法二:直接定位删除
vec.erase(vec.begin() + 3);//删除该容器第4个元素
for (auto&v : vec)
cout << "第二次删除后容器的元素还有:" << v << endl;
//方法三:删除某区间元素
vec.erase(vec.begin(),vec.begin() + 3);//注意左包含而右不包含,只删除第1、2个元素
cout << "第三次删除后容器的元素还有:" << vec.size()<<"个。" << endl;
system("pause");
return 0;
}
输出:

原文链接~:删除vector容器某位置元素的三种简单方法_vector删除对应位置的数据-CSDN博客
贴上官方题解~
今天看官解好像思路很好,挺值得学习的,写了写注释~
class Solution {
public:
int countStudents(vector<int>& students, vector<int>& sandwiches) {
int s1 = accumulate(students.begin(), students.end(), 0);//对所有元素累加,0表累加的初始值,这样累加下来s1记录的是1的个数
int s0 = students.size() - s1;//很妙
for (int i = 0; i < sandwiches.size(); i++) {//该题与队列中学生的相对顺序是无关的,只需关注学生队列中0or1的个数与栈顶是否匹配即可
if (sandwiches[i] == 0 && s0 > 0) {//如果匹配,采用的方法的s0--与i++的方法来控制
s0--;//i++表示三明治并没有实际出队,而是栈顶指针+1,很棒的思路
} else if (sandwiches[i] == 1 && s1 > 0) {
s1--;
} else {
break;
}
}
return s0 + s1;
}
};
作者:力扣官方题解
链接:https://leetcode.cn/problems/number-of-students-unable-to-eat-lunch/solutions/1900373/wu-fa-chi-wu-can-de-xue-sheng-shu-liang-fv3f5/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

浙公网安备 33010602011771号