力扣刷题总结 -- 数组28

82. 无法吃午餐的学生数量(简单)

题目要求:

学校的自助午餐提供圆形方形的三明治,分别用数字 0 和 1 表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。
餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个里,每一轮:
如果队列最前面的学生喜欢栈顶的三明治,那么会拿走它并离开队列。
否则,这名学生会放弃这个三明治并回到队列的尾部
这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。

给你两个整数数组 students 和 sandwiches ,其中 sandwiches[i] 是栈里面第 i​​​​​​ 个三明治的类型(i = 0 是栈的顶部), students[j] 是初始队列里第 j​​​​​​ 名学生对三明治的喜好(j = 0 是队列的最开始位置)。请你返回无法吃午餐的学生数量。

题目分析:

根据题意,我们只需查看队列中与当前栈顶元素匹配的元素数量,而不用关心其先后顺序。如果队列中有元素与当前栈顶元素匹配,则队列中元素个数迟早会减1.按此方法遍历栈中元素,统计最终队列中两类元素的个数之和即可。

题目解答:

#include <iostream>
using namespace std;
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>


class Solution
{
public:
	int countStudents(vector<int>& students, vector<int>& sandwiches)
	{
		int s1 = accumulate(students.begin(), students.end(), 0);  // 获取队列中0的个数
		int s0 = students.size() - s1;  // // 获取队列中1的个数

		for (int i = 0; i < sandwiches.size(); i++)  // 遍历栈
		{
			if (sandwiches[i] == 0 && s0 > 0)
			{
				s0--;  // 吃不上饭的人数减1
			}
			else if (sandwiches[i] == 1 && s1 > 0)
			{
				s1--;  // 吃不上饭的人数减1
			}
			else
			{
				break;
			}
		}

		return s0 + s1;
	}

};


int main()
{
	vector<int> students = { 1,1,0,0 };
	vector<int> sandwiches = { 0,1,0,1 };

	cout << "学生队列为:";
	for (int stu : students)
	{
		cout << stu << ", ";
	}
	cout << endl;

	cout << "三明治栈为:";
	for (int san : sandwiches)
	{
		cout << san << ", ";
	}
	cout << endl;

	Solution s;
	int res = s.countStudents(students, sandwiches);

	cout << "无法吃午餐的学生有" << res << "个" << endl;

	system("pause");
	return 0;
}

83. 卡车上的最大单元数(简单)

题目要求:

将一些箱子装在 一辆卡车上。给定一个二维数组 boxTypes ,其中 boxTypes[i] = [numberOfBoxesi, numberOfUnitsPerBoxi] :

numberOfBoxesi 是类型 i 的箱子的数量。
numberOfUnitsPerBoxi 是类型 i 每个箱子可以装载的单元数量。
整数 truckSize 表示卡车上可以装载 箱子 的 最大数量 。只要箱子数量不超过 truckSize ,就可以选择任意箱子装到卡车上。

返回卡车可以装载单元的最大总数。

题目分析:

由于卡车容量有限,优先将装载单元多的箱子放上卡车,直至卡车达到最大容量即可。对boxTypes按照装载单元大小降序排列,再遍历即可。

题目解答:

#include <iostream>
using namespace std;
#include <string>
#include <vector>
#include <algorithm>


class Solution
{
public:
	int maximumUnits(vector<vector<int>>& boxTypes, int truckSize)
	{
		sort(boxTypes.begin(), boxTypes.end(), [](const vector<int> &a, const vector<int> &b)
		{
			return a[1] > b[1];
		});  // 按照numberOfUnitsPerBox的大小对boxTypes进行重排序

		int res = 0;
		for (auto &boxType : boxTypes)
		{
			int numberOfBoxes = boxType[0];  // 获取当前类箱子的数量
			int numberOfUnitsPerBox = boxType[1];  // 获取当前类每个箱子能够装载的单元数量
			if (numberOfBoxes < truckSize)  // 如果当前箱子数小于卡车容量
			{
				res += numberOfBoxes * numberOfUnitsPerBox;  // 累加装载的单元总数
				truckSize -= numberOfBoxes;  // 将卡车总容量减去已装载的箱子数
			}
			else
			{
				res += truckSize * numberOfUnitsPerBox;  // 如果当前类箱子的数量大于卡车剩下的容量,将卡车剩下容量和每箱单元数的乘积作为最后装载的单元总数
				break;
			}
		}

		return res;
	}
};


int main()
{
	int truckSize = 4;
	vector<vector<int>>boxTypes = { {1,3}, {2,2}, {3,1} };

	cout << "货物情况如下:" << endl;
	for (auto &e : boxTypes)
	{
		for (int num : e)
		{
			cout << num << ", ";
		}
		cout << endl;
	}
	cout << endl;

	Solution s;
	int res = s.maximumUnits(boxTypes, truckSize);

	cout << "卡车可以装载的单元最大总数为:" << res << endl;

	system("pause");
	return 0;
}

84. 在既定时间做作业的学生人数(简单)

题目要求:

给定两个整数数组 startTime(开始时间)和 endTime(结束时间),并指定一个整数 queryTime 作为查询时间。

已知,第 i 名学生在 startTime[i] 时开始写作业并于 endTime[i] 时完成作业。

请返回在查询时间 queryTime 时正在做作业的学生人数。形式上,返回能够使 queryTime 处于区间 [startTime[i], endTime[i]](含)的学生人数。

题目分析:

法1:枚举法
遍历每个学生的startTime[i]和endTime[i],并判断是否startTime[i] ≤ queryTime ≤ endTime[i],如果是,ans+1。

法2:二分查找
设startTime[i] ≤ queryTime的学生集合为lessStart,设endTime[i] ≤ queryTime的学生集合为lessEnd,显然lessEnd ∈ lessStart,将lessStart减去lessEnd就得到符合题意的学生人数。

题目解答:

#include <iostream>
using namespace std;
#include <string>
#include <vector>
#include <algorithm>

// 法1--枚举法
class Solution1
{
public:
	int busyStudent1(vector<int>& startTime, vector<int>& endTime, int queryTime)
	{
		int n = startTime.size();
		int ans = 0;

		// 遍历数组,判断查询时间是否介于开始和结束时间之内
		for (int i = 0; i < n; i++)
		{
			if (startTime[i] <= queryTime && endTime[i] >= queryTime)
			{
				ans++;
			}
		}

		return ans;
	}

};

// 法2--二分查找法
class Solution2
{
public:
	int busyStudent2(vector<int>& startTime, vector<int>& endTime, int queryTime)
	{
		// 对时间进行升序排序
		sort(startTime.begin(), startTime.end());
		sort(startTime.begin(), startTime.end());

		// upper_bound获取数组中第一个大于queryTime的值的位置
		int lessStart = upper_bound(startTime.begin(), startTime.end(), queryTime) - startTime.begin();

		// lower_bound获取数组中第一个大于等于queryTime的值的位置
		int lessEnd = lower_bound(endTime.begin(), endTime.end(), queryTime) - endTime.begin();

		return lessStart - lessEnd;
	}

};


int main()
{
	vector<int> startTime = { 1,2,3 };
	vector<int> endTime = { 3,2,7 };
	int queryTime = 4;
	Solution1 s1;
	Solution2 s2;

	cout << "开始学习的时间为:";
	for (int t : startTime)
	{
		cout << t << ", ";
	}
	cout << endl;

	cout << "结束学习的时间为:";
	for (int t : endTime)
	{
		cout << t << ", ";
	}
	cout << endl;

	cout << "查询时间为:" << queryTime << endl;

	int res1 = s1.busyStudent1(startTime, endTime, queryTime);
	int res2 = s2.busyStudent2(startTime, endTime, queryTime);

	cout << "法1得出的在既定时间工作的学生人数为:" << res1 << endl;
	cout << "法2得出的在既定时间工作的学生人数为:" << res2 << endl;

	system("pause");
	return 0;
}
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值