返回顶部

LeetCode第 67 场双周赛

T1 5934. 找到和最大的长度为 K 的子序列

题目描述: 找到长度为\(k\)的和最大子序列

思路:记录一下下标排序之后选出最大的\(k\)个,然后再排序回去即可。

时间复杂度:\(O(nlogn)\)

参考代码:

class Solution {
public:
    vector<int> maxSubsequence(vector<int>& nums, int k) {
        vector<pair<int , int>> a;
        int n = nums.size();
        for(int i = 0 ; i < n ; ++i) a.push_back({nums[i] , i});
        sort(a.begin() , a.end());
        vector<pair<int, int>> b;
        for(int i = n - 1 ; i >= n - k ; --i) b.push_back({a[i].second , a[i].first});
        vector<int>res;
        sort(b.begin() , b.end());
        for(auto num : b) res.push_back(num.second);
        return res;
    }
};

T2 5935. 适合打劫银行的日子

题目描述:给定\(time\),求出所有满足下述条件的下标

\[security_{i - time} \geq security_{i - time + 1} \geq ... \geq security_i \leq ... \leq security_{i + time - 1} \leq security_{i + time} \]

思路:经典题目,顺着\(dp\)一遍求到当前位置的最长非递增子数组长度,倒着\(dp\)一遍求到当前位置的最长非递减子数组的长度。然后枚举判断即可。

定义\(f_i\)表示从前往后,\(g_i\)表示从后往前,则转移方程为

\[f_i = \begin{cases} 1 & i = 0\\ 1 & i > 1 \;and \;security_{i - 1} < security_i\\ f_{i - 1} + 1 & i>1 \;and\;security_{i -1 } \geq security_i \end{cases} \]

\[g_i = \begin{cases} 1 & i = n - 1\\ 1 & i < n - 1 \;and \;security_{i} > security_{i + 1}\\ g_{i + 1} + 1 & i<n - 1 \;and\;security_{i} \leq security_{i + 1} \end{cases} \]

时间复杂度:\(O(n)\)

参考代码:

class Solution {
public:
    vector<int> goodDaysToRobBank(vector<int>& a, int time) {
        int n = a.size();
        vector<int>f(n + 2 , 0) , g(n + 2 , 0);
        f[1] = 1;
        for(int i = 1 ; i < n ; ++i){
            f[i + 1] = 1;
            if(a[i] <= a[i - 1]) f[i + 1] += f[i];
        }
        g[n] = 1;
        for(int i = n - 2 ; i >= 0 ; --i){
            g[i + 1] = 1;
            if(a[i] <= a[i + 1]) g[i + 1] += g[i + 2];
        }
        vector<int>res;
        for(int i = time + 1 ; i <= n - time ; ++i)
            if(f[i] > time && g[i] > time) res.push_back(i - 1);
        return res;
    }
};

T3 5936. 引爆最多的炸弹

题目描述:给定\(n\)个炸弹,每个炸弹爆炸的同时会引爆在其爆炸范围内的炸弹,问你引爆其中一个炸弹时,实际爆炸的炸弹的总数目最大是多少。

思路:考虑建图,当两个炸弹之间的距离小于等于该炸弹的引爆范围时,建立一条从该炸弹到另一个炸弹的有向边,建好图之后,以每一个炸弹作为起点进行dfs,统计能访问到的点的数目,就是引爆该点炸弹时实际能引爆的炸弹数,取最大即可。

时间复杂度:\(O(n^2)\)

参考代码:

class Solution {
private:
    long long cal(vector<int>& a , vector<int>& b){
        return 1ll * (a[0] - b[0]) * (a[0] - b[0]) + 1ll * (a[1] - b[1]) * (a[1] - b[1]);
    }
    void dfs(vector<vector<int>>& graph , int u , int& cnt, vector<int>& vis){
        if(vis[u] == 1) return ;
        ++cnt;
        vis[u] = 1;
        for(auto v : graph[u]) dfs(graph , v , cnt , vis);
        return ;
    }
    
public:
    int maximumDetonation(vector<vector<int>>& bombs) {
        int n = bombs.size();
        vector<vector<int>>graph(n);
        for(int i = 0 ; i < n ; ++i){
            for(int j = i + 1 ; j < n ; ++j){
                long long dis = cal(bombs[i] , bombs[j]);
                if(dis <= 1ll * bombs[i][2] * bombs[i][2]) graph[i].push_back(j);
                if(dis <= 1ll * bombs[j][2] * bombs[j][2]) graph[j].push_back(i);
            }
        }
        vector<int>vis(n , 0);
        int res = 0;
        for(int i = 0 ; i < n ; ++i){
            int cnt = 0;
            dfs(graph , i , cnt, vis);
            vis = vector<int>(n , 0);
            res = max(res , cnt);
        }
        return res;
    }
};

T4 5937. 序列顺序查询

题目描述:你需要实现一个类,该类具有以下功能:

  • 插入一个字符串和该字符串的\(score\)
  • 询问插入的所有字符串中,第\(k\)好的是什么

一个字符串比另一个字符串好当且仅当该字符串的\(score\)大于另一个字符串的\(score\)或者两者的\(score\)相同但一个字符串的字典序比另一个字符串的字典序小。

询问的参数\(k\)是根据当前询问的次数来定的,比如我第一次询问,\(k = 1\),第二次询问,则\(k = 2\),依次类推

思路:经典题目,考虑维护俩堆,一个小根堆,一个大根堆,小根堆的堆顶元素就是下次要询问的答案,大根堆用于在询问后将小根堆的元素数量\(+1\)
C++考虑使用set进行维护即可。

时间复杂度:\(O(nlogn)\)
C++参考代码:

class SORTracker {
private:
    struct infor{
        int val;
        string name;
        bool operator < (const infor& a)const{
            return val < a.val || (val == a.val && name > a.name);
        }
    };
    set<infor> s , t;
    int cur;
public:
    SORTracker() {
        cur = 0;
    }
    void add(string name, int score) {
        if(s.size() == 0 || s.size() < cur + 1) s.insert({score , name});
        else{
            auto [sc , na] = *s.begin();
            if(sc < score || (sc == score && name < na)) {
                t.insert(*s.begin()) ;
                s.erase(s.begin()) ;
                s.insert({score , name});
            }
            else t.insert({score , name});
        }
        return ;
    }
    
    string get() {
        string res = (*s.begin()).name;
        ++cur;
        if(t.size() != 0){
            s.insert(*t.rbegin());
            t.erase(*t.rbegin());
        }
        return res;
    }
};

Java参考代码:

class SORTracker {
    class infor{
        int val;
        String name;
        infor(int val , String name){
            this.val = val;
            this.name = name;
        }
    }
    private PriorityQueue<infor> heap1, heap2;
    private int  cnt;
    public SORTracker() {
        heap1 = new PriorityQueue<infor>((a , b)->{
            if(a.val != b.val) return a.val - b.val;
            return b.name.compareTo(a.name);
        });
        heap2 = new PriorityQueue<infor>((a , b)->{
            if(a.val != b.val) return b.val - a.val;
            return a.name.compareTo(b.name);
        });
    }
    
    public void add(String name, int score) {
        if(heap1.size() < cnt + 1) heap1.add(new infor(score , name));
        else{
            infor a = heap1.poll();
            if(a.val < score || (a.val == score && name.compareTo(a.name) < 0)){
                heap1.add(new infor(score , name));
                heap2.add(a);
            }
            else{
                heap1.add(a);
                heap2.add(new infor(score , name));
            }
        }
    }
    
    public String get() {
        ++cnt;
        String res = heap1.peek().name;
        if(!heap2.isEmpty())heap1.add(heap2.poll());
        return res;
    }
}

推荐题目:

295. 数据流的中位数

P1168 中位数

P3871 [TJOI2010]中位数

posted @ 2021-12-12 09:33  cherish-lgb  阅读(40)  评论(1编辑  收藏  举报