【力扣每日一题】2022.8.15 - 2022.8.19 八月第三周

俗话说总结才有收获,每日一题栏目从每天一篇水博客到一周一篇水博客啦!下面回顾一下本周做了那些题吧!

[8.15]设计循环双端队列

题目描述

设计实现双端队列。

实现 MyCircularDeque类:

  • MyCircularDeque(int k) :构造函数,双端队列最大为 k 。
  • boolean insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true ,否则返回 false 。
  • boolean insertLast() :将一个元素添加到双端队列尾部。如果操作成功返回 true ,否则返回 false 。
  • boolean deleteFront() :从双端队列头部删除一个元素。 如果操作成功返回 true ,否则返回 false 。
  • boolean deleteLast() :从双端队列尾部删除一个元素。如果操作成功返回 true ,否则返回 false 。
  • int getFront():从双端队列头部获得一个元素。如果双端队列为空,返回 -1 。
  • int getRear() :获得双端队列的最后一个元素。 如果双端队列为空,返回 -1 。
  • boolean isEmpty() :若双端队列为空,则返回 true ,否则返回 false 。
  • boolean isFull() :若双端队列满了,则返回 true ,否则返回 false 。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/design-circular-deque

思路

本题是很简单的模拟题,有两种实现方法:数组实现和链表实现,下面介绍链表实现:

  • 定义一个size用来表示当前链表所存储元素的数量,capacity用来表示能存储的最大数量;定义一个双向链表用来表示队列。
  • 如何判断队列为空:size == 0;
  • 如何判断队列为满:size == capacity;

代码实现

// cpp实现
struct DLinkListNode {
    int val;
    DLinkListNode *prev, *next;
    DLinkListNode(int _val): val(_val), prev(nullptr), next(nullptr) {

    }
};

class MyCircularDeque {
private:
    DLinkListNode *head, *tail;
    int capacity;
    int size;

public:
    MyCircularDeque(int k): capacity(k), size(0), head(nullptr), tail(nullptr) {
        
    }

    bool insertFront(int value) {
        if (size == capacity) {
            return false;
        }
        DLinkListNode *node = new DLinkListNode(value);
        if (size == 0) {
            head = tail = node;
        } else {
            node->next = head;
            head->prev = node;
            head = node;
        }
        size++;
        return true;
    }

    bool insertLast(int value) {
        if (size == capacity) {
            return false;
        }
        DLinkListNode *node = new DLinkListNode(value);
        if (size == 0) {
            head = tail = node;
        } else {
            tail->next = node;
            node->prev = tail;
            tail = node;
        }
        size++;
        return true;
    }

    bool deleteFront() {
        if (size == 0) {
            return false;
        }
        DLinkListNode *node = head;
        head = head->next;
        if (head) {
            head->prev = nullptr;
        }
        delete node;
        size--;
        return true;
    }

    bool deleteLast() {
        if (size == 0) {
            return false;
        }
        DLinkListNode *node = tail;
        tail = tail->prev;
        if (tail) {
            tail->next = nullptr;
        }
        delete node;
        size--;
        return true;
    }

    int getFront() {
        if (size == 0) {
            return -1;
        }
        return head->val;
    }

    int getRear() {
        if (size == 0) {
            return -1;
        }
        return tail->val;
    }

    bool isEmpty() {
        return size == 0;
    }

    bool isFull() {
        return size == capacity;
    }
};

[8.16]设计有序流

题目描述

有 n 个 (id, value) 对,其中 id 是 1 到 n 之间的一个整数,value 是一个字符串。不存在 id 相同的两个 (id, value) 对。

设计一个流,以 任意 顺序获取 n 个 (id, value) 对,并在多次调用时 按 id 递增的顺序 返回一些值。

实现 OrderedStream 类:

  • OrderedStream(int n) 构造一个能接收 n 个值的流,并将当前指针 ptr 设为 1 。
  • String[] insert(int id, String value) 向流中存储新的 (id, value) 对。存储后:
  • 如果流存储有 id = ptr 的 (id, value) 对,则找出从 id = ptr 开始的 最长 id 连续递增序列 ,并 按顺序 返回与这些 id 关联的值的列表。然后,将 ptr 更新为最后那个 id + 1 。
  • 否则,返回一个空列表。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/design-an-ordered-stream

思路

按照题目描述模拟即可

代码实现

class OrderedStream {
public:
    vector<string> strs;
    int ptr;
    OrderedStream(int n) {
        strs.resize(n + 1);
        ptr = 1;
    }
    
    vector<string> insert(int idKey, string value) {
        strs[idKey] = value;
        vector<string> res;
        while(ptr < strs.size() && !strs[ptr].empty()){
            res.emplace_back(strs[ptr]);
            ptr++;
        }
        return res;
    }
};

/**
 * Your OrderedStream object will be instantiated and called as such:
 * OrderedStream* obj = new OrderedStream(n);
 * vector param_1 = obj->insert(idKey,value);
 */

[8.17]层数最深叶子节点的和

题目描述

给你一棵二叉树的根节点 root ,请你返回 层数最深的叶子节点的和

题目链接:https://leetcode.cn/problems/deepest-leaves-sum/

思路

这道题没啥好说的,层序遍历完事儿,初学二叉树遍历的朋友可以拿这道题试试手。

代码实现

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int deepestLeavesSum(TreeNode* root) {
        // 层次遍历
        vector<int> treeList;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty()){
            int size = q.size();
            int sum = 0;
            while(size--){
                TreeNode *temp = q.front();
                q.pop();
                sum+=temp->val;
                if(temp->left){
                    q.push(temp->left);
                }
                if(temp->right){
                    q.push(temp->right);
                }
            }
            treeList.emplace_back(sum);
        }
        return treeList[treeList.size()-1];
    }
};

[8.18] 最大相等频率

给你一个正整数数组 nums,请你帮忙从该数组中找出能满足下面要求的 最长 前缀,并返回该前缀的长度:

从前缀中 恰好删除一个 元素后,剩下每个数字的出现次数都相同。

  • 如果删除这个元素后没有剩余元素存在,仍可认为每个数字都具有相同的出现次数(也就是 0 次)。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-equal-frequency

思路

更改最长前缀的情况有以下三种:

  • 遍历到第i个元素时,所有已经遍历过的元素的出现次数均为 1,此时可以将最长前缀 res + 1
  • 遍历至第 i 个元素时,若满足最大出现次数_max乘以出现次数为_max 的元素个数 + 1 == 当前遍历长度length, 则更新最长前缀为 length。
  • 遍历至第 i 个元素时,若满足 (_max - 1) * ( sum[_max - 1] + 1 ) + 1 = length,则更新最长前缀。

代码实现

class Solution {
public:
    int maxEqualFreq(vector<int>& nums) {
        vector<int> freq(100010,0); // 记录某个数字的出现次数
        vector<int> sum(100010,0);
        int n = nums.size();
        int _max = 1; // 记录最大的出现次数
        int res = 1;
        for(int i = 0; i < n; i++){
            int t = nums[i];
            int cur = ++freq[t];
            int length = i + 1;
            sum[cur]++; // 出现次数为cur的数的次数
            sum[cur - 1]--;
            _max = max(_max, cur);
            if(_max == 1) res = length;
            if(_max * sum[_max] + 1 == length) res = length;
            if((_max - 1) * (sum[_max - 1] + 1) + 1 == length) res = length;
        }
        return res;
    }
};

[8.19]在既定时间做作业的学生人数

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/number-of-students-doing-homework-at-a-given-time
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

暴力法当然时能做的,毕竟是一道简单题嘛;
但是翻看题解我发现了一种新的方法:差分数组,本题是一道差分数组的经典模板题.

算法实现

class Solution {
public:
    int busyStudent(vector<int>& startTime, vector<int>& endTime, int queryTime) {
        // 差分数组
        vector<int> c(1010);
        int n = startTime.size();
        for(int i = 0; i < n; i++){
            c[startTime[i]]++;
            c[endTime[i]+1]--;
        }
        for(int i = 1; i <= queryTime; i++){
            c[i] += c[i-1];
        }
        return c[queryTime];
    }
};

你可能感兴趣的:(每日一题,leetcode,链表,算法)