线程池与任务队列(Task-Queue)

队列基础知识

  • 入队
  • 出队
  • 假溢出
  • 循环队列

实现方式

普通队列

class Queue{
public:
  Queue(int n) : arr(n), head(0), tail(0){}
  //入队
  void push(int x){
    if(full()){
      cout << "queue full" << endl;
    }
    arr[tail] = x;
    tail += 1;
    return ;
  }
  //出队 
  void pop(){
    if(empty()) return;
    head +=1 ;
  } 
  //判空
  bool empty(){
    return head == tail;
  }
  //判满 
  bool full(){
    return tail = arr.size();
  } 
  //查看队首元素
  int front(){
    return arr[head];
  }
  int size(){
    return tail - head;
  }
  void output(){
    cout<<"Queue: ";
    for(int i = head ; i < tail ; i++){
       cout << arr[i] << ""; 
    }
    cout << endl;
  }
private:
  int head, tail;
  vector<int> arr;
}

循环队列

class Queue{
public:
  Queue(int n) : arr(n), head(0), tail(0), cnt(0){}
  //入队
  void push(int x){
    if(full()){
      cout << "queue full" << endl;
    }
    arr[tail] = x;
    tail += 1;
    cnt += 1;
    if(tail == arr.size()) tail = 0;
    return ;
  }
  //出队 
  void pop(){
    if(empty()) return;
    head +=1 ;
    cnt -= 1;
    if(head == arr.size()) tail = 0
  } 
  //判空
  bool empty(){
    return cnt = 0;
  }
  //判满 
  bool full(){
    return cnt = arr.size();
  } 
  //查看队首元素
  int front(){
    return arr[head];
  }
  int size(){
    return cnt;
  }
  void output(){
    cout<<"Queue: ";
    for(int i = 0 , j =head ; i < cnt ; i++){
       cout << arr[j] << ""; 
       j += 1;
       if(j == arr.size()) j = 0;
    }
    cout << endl;
  }
  void clear(){
    head = tail = cnt = 0;
  }
private:
  int head, tail;
  int cnt;
  vector<int> arr;
}

队列的典型应用场景

场景一: CPU的超线程技术
在这里插入图片描述
在这里插入图片描述
虚拟四核: 给每个核心增加一条指令队列
多路CPU: CPU1 CPU2 CPU3…
一个CPU包含多个计算核心, 多路CPU包含多个CPU

场景二: 线程池的任务队列

在这里插入图片描述
普通的多线程程序问题: 频繁的申请和销毁, 效率大打折扣
在这里插入图片描述
任务队列: 任务的缓冲区

经典面试题 - 链表复习题

86.分隔链表
设置两个头指针,将所有小于的插入到第一个链表中,将所有大于的插入到第二个链表中,最后将这两个链表合成一段

class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode r1 , r2 , *p1 = &r1 , *p2=&r2  , *p = head, *q;
        while(p){
            q = p->next;
            if(p->val < x){
                p->next = p1->next;
                p1->next = p;
                p1 = p;
            } else {
                p->next = p2->next;
                p2->next = p;
                p2 = p;
            }
            p = q;
        }
        p1->next = r2.next;
        return r1.next;
    }
};

138. 复制带随机指针的链表
思路:

  • 将原来的链表两两一组进行复制(包含random节点),如下
    原链表 1->2->3->4
    复制后的链表 1->1’->2->2’->3->3’->4->4’
  • 此时原节点和复制节点的random节点都指向同一位,需要将复制节点的random指向下一位
  • 将链表每两个节点拆成一个新链表
class Solution {
public:
    Node* copyRandomList(Node* head) {
        if(head == nullptr) return nullptr;
        Node *p = head, *q, *new_head;
        while(p){
            q = new Node(p->val);
            q->random = p->random;
            q->next = p->next;
            p->next = q;
            p = q->next;
        }
        p = head->next;
        while(p){
            if(p->random) p->random = p->random->next;
            (p = p->next) && (p = p->next);
        }
        new_head = head->next;
        p = head;
        while(p){
            q = p->next;
            p->next = q->next;
            if(p->next) q->next = p->next->next;
            p = p->next;
        }
        return new_head;
    }
};

经典面试题 - 队列

622. 设计循环队列

class MyCircularQueue {
public:
    vector<int> arr;
    int head, tail, cnt;
    MyCircularQueue(int k) : arr(k), head(0), tail(0), cnt(0){}
    
    bool enQueue(int value) {
        if(isFull()) return false;
        arr[tail] = value;
        tail = (tail + 1) % arr.size();
        cnt += 1;
        return true;
    }
    
    bool deQueue() {
        if(isEmpty()) return false;
        head = (head + 1) % arr.size();
        cnt -= 1;
        return true;
    }
    
    int Front() {
        if(isEmpty()) return -1;
        return arr[head];
    }
    
    int Rear() {
        if(isEmpty()) return -1;
        return arr[(tail - 1 + arr.size()) % arr.size()];
    }
    
    bool isEmpty() {
        return cnt == 0;
    }
    
    bool isFull() {
        return cnt == arr.size();
    }
};

641. 设计循环双端队列

class MyCircularDeque {
public:
    vector<int> arr;
    int cnt, head, tail;
    MyCircularDeque(int k) : arr(k), head(0), tail(0), cnt(0){}
    
    bool insertFront(int value) {
        if(isFull()) return false;
        head = head - 1;
        if(head == -1) head = arr.size() - 1;
        arr[head] = value;
        cnt += 1;
        return true;
    }
    
    bool insertLast(int value) {
        if(isFull()) return false;
        arr[tail] = value;
        tail += 1;
        if(tail == arr.size()) tail = 0;
        cnt += 1;
        return true;
    }
    
    bool deleteFront() {
        if(isEmpty()) return false;
        head = (head + 1) % arr.size();
        cnt -= 1;
        return true;
    }
    
    bool deleteLast() {
        if(isEmpty()) return false;
        tail = (tail - 1 + arr.size()) % arr.size();
        cnt -= 1;
        return true;
    }
    
    int getFront() {
        if(isEmpty()) return -1;
        return arr[head];
    }
    
    int getRear() {
        if(isEmpty()) return -1;
        return arr[(tail - 1 + arr.size()) % arr.size()];
    }
    
    bool isEmpty() {
        return cnt == 0;
    }
    
    bool isFull() {
        return cnt == arr.size();
    }
};

1670.设计前中后队列

class Node{
public:
    int val;
    Node *next, *pre;
    Node(int val = 0, Node *next = nullptr, Node *pre = nullptr) : val(val), next(next), pre(pre){}
    void insert_pre(Node *p){
        p->pre = pre;
        p->next = this;
        if(this->pre) this->pre->next = p;
        this->pre = p;
        return;
    }
    void insert_next(Node *p){
        p->pre = this;
        p->next = this->next;
        if(this->next) this->next->pre = p;
        this->next = p;
        return;
    }
    void delete_pre(){
        if(this->pre == nullptr) return;
        Node *p = this->pre;
        this->pre = p->pre;
        if(p->pre) p->pre->next = this;
        delete p;
        return;
    }
    void delete_next(){
        if(this->next == nullptr) return;
        Node *p = this->next;
        this->next = p->next;
        if(p->next) p->next->pre = this;
        delete p;
        return;
    }
};

class Queue {
public:
    int cnt;
    Node head, tail;
    Queue(): cnt(0){
        head.next = &tail;
        head.pre = nullptr;
        tail.next = nullptr;
        tail.pre = &head;
    }
    void push_back(int val){
        tail.insert_pre(new Node(val));
        cnt += 1;
        return;
    }
    void push_front(int val){
        head.insert_next(new Node(val));
        cnt += 1;
        return;
    }
    int pop_back(){
        if(isEmpty()) return -1;
        int ret = tail.pre->val;
        cnt -= 1;
        tail.delete_pre();
        return ret;
    }
    int pop_front(){
        if(isEmpty()) return -1;
        int ret = head.next->val;
        cnt -= 1;
        head.delete_next();
        return ret;
    }
    int front(){
        return head.next->val;
    }
    int back(){
        return tail.pre->val;
    }
    bool isEmpty(){
        return head.next == &tail;
    }
    int size(){
        return cnt;
    }
};

class FrontMiddleBackQueue {
public:
    Queue q1, q2;
    FrontMiddleBackQueue() {}

    void pushFront(int val) {
        q1.push_front(val);
        update();
        return;
    }
    
    void pushMiddle(int val) {
        if(q1.size() > q2.size()){
            q2.push_front(q1.back());
            q1.pop_back();
        }
        q1.push_back(val);
        return;
    }
    
    void pushBack(int val) {
        q2.push_back(val);
        update();
        return;

    }
    
    int popFront() {
        if(isEmpty()) return -1;
        int ret = q1.pop_front();
        update();
        return ret;
    }
    
    int popMiddle() {
        if(isEmpty()) return -1;
        int ret = q1.pop_back();
        update();
        return ret;
    }
    
    int popBack() {
        if(isEmpty()) return -1;
        int ret;
        if(q2.isEmpty()){
            ret = q1.pop_back();
        }else{
            ret = q2.pop_back();
        }
        update();
        return ret;
    }

    bool isEmpty(){
        return q1.size() + q2.size() == 0;
    }

    void update() {
        if(q1.size() < q2.size()){
            q1.push_back(q2.front());
            q2.pop_front();
        }
        if(q1.size() == q2.size() + 2){
            q2.push_front(q1.back());
            q1.pop_back();
        }
        return;
    }
};

933.最近请求次数

  • 每次请求时入队
  • 与队首比较,超出3000毫秒的出队
  • 返回队列长度
class RecentCounter {
public:
    queue<int> q;
    RecentCounter() {

    }
    
    int ping(int t) {
        q.push(t);
        while(t - q.front() > 3000) q.pop();
        return q.size();
    }
};

经典面试题-智力发散题

面试题 17.09. 第 k 个数

  • 生成一个队列,设置p3,p5,p7三个指针
  • 分别用指针指向的值乘3,乘5,乘7,取其中最小值压入,然后该指针向后移一位(如果两个指针算出来的值相同,那就同时往后移动一位)
class Solution {
public:
    int getKthMagicNumber(int k) {
        vector<int> arr;
        arr.push_back(1);
        int p3 = 0, p5 = 0, p7 = 0;
        while(arr.size() < k){
            int ans = 3 * arr[p3];
            ans = min(ans, 5 * arr[p5]);
            ans = min(ans, 7 * arr[p7]);
            if(3 * arr[p3] == ans) p3++;
            if(5 * arr[p5] == ans) p5++;
            if(7 * arr[p7] == ans) p7++;
            arr.push_back(ans);
        }
        return arr[k-1];
    }
};

860.柠檬水找零

  • 给10元 只能找零5元
  • 给20元 1.找零一张10元 一张5元 2.三张5元 优先一张10元一张5元
class Solution {
public:
     bool lemonadeChange(vector<int>& bills) {
        int five = 0, ten = 0;
        for (auto & bill: bills) {
            if (bill == 5) {
                five++;
            } else if (bill == 10) {
                if (five == 0) {
                    return false;
                }
                five--;
                ten++;
            } else {
                if (five > 0 && ten > 0) {
                    five--;
                    ten--;
                } else if (five >= 3) {
                    five -= 3;
                } else {
                    return false;
                }
            }
        }
        return true;
    } 
};

621. 任务调度器

class Solution {
public:
    int leastInterval(vector<char>& tasks, int n) {
        int cnt[26] = {0};
        for(int i = 0;i < tasks.size(); i++) cnt[tasks[i] - 'A'] += 1;
        sort(cnt, cnt + 26);
        int m = 0;
        for(int i = 25; i>=0 && cnt[i] == cnt[25]; i--, m++);
        return max((int)tasks.size(), ( cnt[25] -1 ) * ( n + 1 ) + m);
    }
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值