六月集训(第16天)—队列

队列

1. 933. 最近的请求次数

    思路:
        让请求时间入队,让队首请求时刻小于t-3000的请求出队,返回队列中的请求个数。

class RecentCounter {
    int front, rear;
    int data[10010];
public:
    RecentCounter() {
        front = 0;
        rear = -1;
    }
    
    int ping(int t) {
        data[++rear] = t;
        while (rear - front >= 0 && data[front] < t - 3000) {
            front++;
        }
        return rear - front + 1;
    }
};

/**
 * Your RecentCounter object will be instantiated and called as such:
 * RecentCounter* obj = new RecentCounter();
 * int param_1 = obj->ping(t);
 */

2. 1700. 无法吃午餐的学生数量

    思路:
        将不喜欢吃栈顶午餐的学生放入队尾,队首后移,直到匹配到喜欢吃栈顶午餐的学生,午餐弹出栈顶,学生减少一人。cnt用于记录匹配学生的次数,如果所有学生匹配完一轮全都不喜欢栈顶午餐,则结束匹配,返回队列中的学生数量。

class Solution {
public:
    int countStudents(vector<int>& students, vector<int>& sandwiches) {
        int n = students.size();
        int front = 0, rear = n - 1;
        int cnt = 0;
        for (int i = 0; i < n; ++i) {
            cnt = rear - front + 1;
            while (students[front] != sandwiches[i]) {
                students.push_back(students[front++]);
                rear++;
                cnt--;
                if (cnt == 0) return rear - front + 1;
            }
            front++;
        }
        return 0;
    }
};

3. 2073. 买票需要的时间

    思路:
        将tickets[]作为一个队列,如果某个人票没买够,则在队尾再次入队,需要买的票数-1。记录k的位置,当到达k人时,判断该人是否已经买完票了,没买完就再次入队,更新k的位置为队尾;如果买完了,结束循环,返回买票时间。

class Solution {
public:
    int timeRequiredToBuy(vector<int>& tickets, int k) {
        int front = 0, rear = tickets.size() - 1;
        int cnt = 0;
        while (rear - front + 1) {
            cnt++;	// 记录买票时间
            if (tickets[front] > 1) {
                tickets.push_back(tickets[front]-1);	// 再次入队,需要买的票数-1
                rear++;
                if (front == k) k = rear;
                front++;
            } else {
                if (front == k) break;	// 第k个人买完了,结束循环,返回时间
                front++;
            }
        }
        return cnt;
    }
};

4. 239. 滑动窗口最大值

    思路:
        滑动窗口区间最大值,用单调递减队列来维护。
         (1) 窗口每滑动一下,取单调队列的队首元素为当前区间的最大值,如果此时窗口的起始位置的值和单调队列左端的值相同,则队首出队(因为该元素不再属于当前窗口的区间)
         (2) 窗口滑动一下,考虑将新加入的元素放入单调队列,将小于该元素的值从队尾依次出队,直到出现比当前元素大的值,或者队为空时,将该元素加入队尾。

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> ans;
        deque<int> q;
        int nums_size = nums.size();
        for (int i = 0; i < nums_size; ++i) {
            while (!q.empty() && q.back() < nums[i]) q.pop_back();
            q.push_back(nums[i]);
            if (i >= k - 1) {
                ans.push_back(q.front());
                if (nums[i - k + 1] == q.front()) q.pop_front();
            }
        }
        return ans;
    }
};
posted @ 2022-06-16 13:17  番茄元  阅读(28)  评论(0)    收藏  举报