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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

posted @ 2024-03-15 15:23  蔡姬小媛  阅读(89)  评论(0)    收藏  举报