文章目录
前言
。。。。。。。。。。。
刷题坚持每一天,以下题目引用自:力扣(LeetCode)
💎一、题目一
🏆1.题目描述
原题链接:933. 最近的请求次数
写一个 RecentCounter 类来计算特定时间范围内最近的请求。
请你实现 RecentCounter 类:
- RecentCounter() 初始化计数器,请求数为 0 。
- int ping(int t) 在时间 t 添加一个新请求,其中 t 表示以毫秒为单位的某个时间,并返回过去 3000 毫秒内发生的所有请求数(包括新请求)。确切地说,返回在 [t-3000, t] 内发生的请求数。
保证 每次对 ping 的调用都使用比之前更大的 t 值。
示例 1:
输入:
[“RecentCounter”, “ping”, “ping”, “ping”, “ping”]
[[], [1], [100], [3001], [3002]]
输出:
[null, 1, 2, 3, 3]
解释:
RecentCounter recentCounter = new RecentCounter();
recentCounter.ping(1); // requests = [1],范围是 [-2999,1],返回 1
recentCounter.ping(100); // requests = [1, 100],范围是 [-2900,100],返回 2
recentCounter.ping(3001); // requests = [1, 100, 3001],范围是 [1,3001],返回 3
recentCounter.ping(3002); // requests = [1, 100, 3001, 3002],范围是 [2,3002],返回 3
🏆2.解题思路
🔑思路:
每一个新请求都入队,然后再判断队首的的请求时间是否在新请求之后的3000里,不在则出队。
🏆3.代码详解
typedef struct {
int queue[10001];
int head;
int tail;
} RecentCounter;
RecentCounter* recentCounterCreate() {
RecentCounter* obj = (RecentCounter*)malloc(sizeof(RecentCounter));
obj->head = 0;
obj->tail = 0;
return obj;
}
int recentCounterPing(RecentCounter* obj, int t) {
obj->queue[obj->tail++] = t;
while(obj->queue[obj->head] < obj->queue[obj->tail-1]-3000){
++obj->head;
}
return obj->tail - obj->head;
}
void recentCounterFree(RecentCounter* obj) {
free(obj);
}
💎二、题目二
🏆1.题目描述
原题链接:1700. 无法吃午餐的学生数量
学校的自助午餐提供圆形和方形的三明治,分别用数字 0 和 1 表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。
餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个 栈 里,每一轮:
- 如果队列最前面的学生 喜欢 栈顶的三明治,那么会 拿走它 并离开队列。
- 否则,这名学生会 放弃这个三明治 并回到队列的尾部。
这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。
给你两个整数数组 students 和 sandwiches ,其中 sandwiches[i] 是栈里面第 i 个三明治的类型(i = 0 是栈的顶部), students[j] 是初始队列里第 j 名学生对三明治的喜好(j = 0 是队列的最开始位置)。请你返回无法吃午餐的学生数量。
示例 1:
输入:students = [1,1,0,0], sandwiches = [0,1,0,1]
输出:0
解释:
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [1,0,0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [0,0,1,1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [0,1,1],三明治栈为 sandwiches = [1,0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [1,1,0]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [1,0],三明治栈为 sandwiches = [0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [0,1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [1],三明治栈为 sandwiches = [1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [],三明治栈为 sandwiches = []。
所以所有学生都有三明治吃。
🏆2.解题思路
🔑思路:
先统计喜欢方形和圆形的各总人数,然后在根据栈顶三明治形状,判断有多少人吃不到三明治。
🏆3.代码详解
int countStudents(int* students, int studentsSize, int* sandwiches, int sandwichesSize){
int ans[2] = {0};
int i;
for(i = 0; i < studentsSize; ++i)
++ans[students[i]];
for(i = 0; i < sandwichesSize; ++i){
if(ans[sandwiches[i]] == 0) break;
--ans[sandwiches[i]];
}
return ans[0] + ans[1];
}
💎三、题目三
🏆1.题目描述
原题链接:2073. 买票需要的时间
有 n 个人前来排队买票,其中第 0 人站在队伍 最前方 ,第 (n - 1) 人站在队伍 最后方 。
给你一个下标从 0 开始的整数数组 tickets ,数组长度为 n ,其中第 i 人想要购买的票数为 tickets[i] 。
每个人买票都需要用掉 恰好 1 秒 。一个人 一次只能买一张票 ,如果需要购买更多票,他必须走到 队尾 重新排队(瞬间 发生,不计时间)。如果一个人没有剩下需要买的票,那他将会 离开 队伍。
返回位于位置 k(下标从 0 开始)的人完成买票需要的时间(以秒为单位)。
示例 1:
输入:tickets = [2,3,2], k = 2
输出:6
解释:
第一轮,队伍中的每个人都买到一张票,队伍变为 [1, 2, 1] 。
第二轮,队伍中的每个都又都买到一张票,队伍变为 [0, 1, 0] 。
位置 2 的人成功买到 2 张票,用掉 3 + 3 = 6 秒。
🏆2.解题思路
🔑思路:
每次买完票都出队,判断
k
位置的人是否需要买票,不需要返回时间。需要则在入队,直至k
位置的人不需要买票;
🏆3.代码详解
typedef struct {
int queue[10010];
int head;
int tail;
} RecentCounter;
int timeRequiredToBuy(int* tickets, int ticketsSize, int k){
RecentCounter* obj = (RecentCounter*)malloc(sizeof(RecentCounter));
obj->head = 0;
obj->tail = 0;
int time = 0;
int flag = 0;
for(int i = 0; i < ticketsSize; ++i){
obj->queue[obj->tail++] = tickets[i] -= 1;
++time;
if(i == k && tickets[i] == 0) return time;
}
while(1){
obj->queue[obj->head] -= 1;
obj->queue[obj->tail++] = obj->queue[obj->head];
if(obj->queue[obj->head] >= 0) ++time;
if(k == flag && obj->queue[obj->head] == 0) return time;
++obj->head;
++flag;
if(flag == ticketsSize){
flag = 0;
}
}
return;
}
💎四、题目四
🏆1.题目描述
原题链接:239. 滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
🏆2.解题思路
🔑思路:
双端队列里保持单调递减,当前元素比队顶元素大则队顶元素出队,当前元素进队,当队列里的元素满足
k
或k以上
,把队头放入结果数组。判断队列里元素是否超出k
个,超出则队头出队。
🏆3.代码详解
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize){
int* ans = (int*)malloc(sizeof(int)*numsSize);
int idx = 0;
int queue[numsSize];
int head = 0, tail = 0;
for(int i = 0; i < numsSize; ++i){
while(head < tail && nums[queue[tail-1]] < nums[i]) --tail;
queue[tail++] = i;
if(i >= k-1){
ans[idx++] = nums[queue[head]];
if(head < tail && i - queue[head] >= k-1) ++head;
}
}
*returnSize = idx;
return ans;
}
💎五、星球推荐
星球链接:英雄算法联盟
星球里有什么?
【朋友圈】一个极致精准的自律、编程、算法的小圈子。
【算法集训】以月为单位组织算法集训,每天四题,风雨无阻。
【排行榜】每天、每周都会有榜单,激励大家不断进步,不断成长。
【个人规划】每个人都写好自己的规划,也可以查看他人的规划,时刻警醒自己不掉队。
【打卡挑战】每日一题打卡、每日早起打卡、算法集训打卡、规划完成情况打卡。
在星球里做什么?
目前星球人数达到520+,在星球里你能够遇到一群志同道合之人,因为都是花钱进来的,你不会看到任何浑水摸鱼的人,每个人都有自己的每月规划,星主每月都会组织算法集训,每天一起刷题,你可以看到别人的解题报告,取其之长,补己之短。