五月刷题16——队列


今日刷题内容: 队列

前言

  • 一个算法废材的刷题之路开更了, 更新每天刷题的题解内容
  • 注重个人理解,看难度更新题目数量
  • 题目来源于力扣
  • 新开专栏,争取每日都能做出至少一题=v=
  • 语言java、python、c\c++

一、今日题目

  1. 933. 最近的请求次数★☆☆☆☆
  2. 2073. 买票需要的时间★☆☆☆☆
  3. 641. 设计循环双端队列★★☆☆☆
  4. 1670. 设计前中后队列★★☆☆☆

二、解题思路

1. 933. 最近的请求次数★☆☆☆☆

并没有用队列的思想来解决本题

  1. 已知传入的t是严格递增的
  2. 只需一个数组用来维护之前输入的值
  3. 每次遍历从当前值向下找在[t-3000, t]之间的元素个数,相加即是答案
class RecentCounter {
    int count = 0;
    int[] temp;
    public RecentCounter() {
        temp =  new int[10010];
    }
    
    public int ping(int t) {
        temp[count++] = t;
        int ret = 0;
        for(int i = count - 1; i >= 0; i--){
            if(temp[i] >= t - 3000 && temp[i] <= t){
                ret++;
            }else{
                break;
            }
        }
        return ret;
    }
}

2. 2073. 买票需要的时间★☆☆☆☆

依旧是按照自己的想法来解题的

  1. 需求第k个顾客排队买到票所需的时间
  2. 当tickets[k] > 0时遍历数组即可
  3. 每次遍历如果当前元素大于0,将当前元素–,再将sum++
  4. 如果i = tickets的长度,再把i置为0即可
class Solution {
    public int timeRequiredToBuy(int[] tickets, int k) {
        int sum = 0;  // 所需时间
        int n = tickets.length;
        int i = 0;
        // 直接对数组进行操作,判断遍历判断第k个元素是否大于0
        while(tickets[k] > 0){
            if(tickets[i] >= 1){
                tickets[i]--;
                sum++;
            }
            i++;
            if (i == n) i = 0;
        }
        
        return sum;
    }
}

3. 641. 设计循环双端队列★★☆☆☆

  1. 可以用数组来实现,因为和第四题比较类似,可以参考第四题,就不写本题的题解了
class MyCircularDeque {
    // 用数组实现
    int[] list;
    int front = 2500;
    int last = front - 1;
    int size;

    public MyCircularDeque(int k) {
        list = new int[5000];
        size = k;
    }
    public int getSize(){
        return front - last - 1;
    }
    public boolean insertFront(int value) {
        if (getSize() == size){
            return false;
        }
        list[front++] = value;
        return true;
    }
    
    public boolean insertLast(int value) {
        if (getSize() == size){
            return false;
        }
        list[last--] = value;
        return true;
    }
    
    public boolean deleteFront() {
        if (getSize() == 0){
            return false;
        }
        front--;
        return true;
    }
    
    public boolean deleteLast() {
        if (getSize() == 0){
            return false;
        }
        last++;
        return true;
    }
    
    public int getFront() {
        if (getSize() == 0){
            return -1;
        }
        return list[front-1];
    }
    
    public int getRear() {
        if (getSize() == 0){
            return -1;
        }
        return list[last+1];
    }
    
    public boolean isEmpty() {
        return getSize() == 0;
    }
    
    public boolean isFull() {
        return getSize() == size;
    }
}

4.1670. 设计前中后队列★★☆☆☆

  1. 这题主要注意的是从中间插入和从中间取出
  2. 每次从中间插入的时候,位置都位于队首指针+队列长度/2的位置
  3. 每次从中间取出时,情况则不同(并没有用英雄哥的数学归纳法)
  1. 当队列元素为1或2时,都是取队首的第一个元素
  2. 当队列元素个数为奇数时,要取的元素位于队首指针 + 队列长度/2 +1的位置
  3. 当队列元素个数为偶数数时,要取的元素位于队首指针 + 队列长度/2的位置
  1. 取到元素后,将整个队首元素后移即可
class FrontMiddleBackQueue {
    int[] list;
    int front = 2500;
    int last = front + 1;
    public FrontMiddleBackQueue() {
        list = new int[5000];
    }
    
    public int getSize(){
        return last - front - 1;  // 获取队列长度
    }
    
    public boolean isEmpty(){
        return getSize() == 0;  // 判断队列是否为空
    }
    
    public boolean isOdd(int num){
        return num % 2 == 1;  // 判断当前队列元素个数是否为奇数个
    }
    
    public void pushFront(int val) {
        list[front--] = val;
    } 
    
    public void pushMiddle(int val) {
        int idx = 0;
        idx = front + getSize() / 2;
        for(int i = front; i < idx; i++){
            list[i] = list[i+1];
        }
        front--;
        list[idx] = val;
    }
    
    public void pushBack(int val) {
       list[last++] = val;
    }
    
    public int popFront() {
        if (isEmpty()){
            return -1;
        }
        return list[++front];
    }
    
    public int popMiddle() {
        if (isEmpty()){
            return -1;
        }
        if(getSize() == 1 || getSize() == 2){
            return list[++front];
        }
        int idx = 0;
        if ( isOdd(getSize()) ){
            idx = front + getSize() / 2 + 1;
        }else{
            idx = front + getSize() / 2;
        }
        int temp = list[idx];
        for(int i = idx; i > front; i--){
            list[i] = list[i-1];
        }
        front++;
        return temp;
    }
    
    public int popBack() {
         if (isEmpty()){
            return -1;
        }
        return list[--last];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值