返回顶部

LeetCode第 284 场周赛题解

6031. 找出数组中的所有 K 近邻下标

题目描述:给你一个下标从 \(0\) 开始的整数数组 \(nums\) 和两个整数 \(key\)\(k\)\(k\) 近邻下标 是 \(nums\) 中的一个下标 \(i\) ,并满足至少存在一个下标\(j\) 使得 \(|i - j| \leq k\)\(nums[j] == key\)

以列表形式返回按 递增顺序 排序的所有 \(k\) 近邻下标。

思路:考虑到\(n\)很小,直接暴力模拟即可

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

参考代码:

class Solution {
public:
    vector<int> findKDistantIndices(vector<int>& nums, int key, int k) {
        int n = nums.size();
        vector<int>res;
        for(int i = 0 ; i < n ; ++i){
            for(int j = max(0 , i - k) ; j < min(n , i + k + 1) ; ++j){
                if(nums[j] != key) continue;
                res.push_back(i);
                break;
            }
        }
        return res;
    }
};

5203. 统计可以提取的工件

题目描述:自己读题

思路:比较明显的二维前缀和,根据题意模拟即可

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

参考代码:

class Solution {
public:
    int digArtifacts(int n, vector<vector<int>>& artifacts, vector<vector<int>>& dig) {
        vector<vector<int>>grid(n + 1 , vector<int>(n + 1 , 0));
        for(auto& vec : dig){
            int u = vec[0] + 1, v = vec[1] + 1;
            grid[u][v] = 1;
        }
        for(int i = 1 ; i <= n ; ++i){
            for(int j = 1 ; j <= n ; ++j){
                grid[i][j] = grid[i][j] + grid[i - 1][j] + grid[i][j - 1] - grid[i - 1][j - 1];
            }
        }
        int res = 0;
        for(auto& vec : artifacts){
            int a = vec[0] + 1 , b = vec[1] + 1, c = vec[2] + 1, d = vec[3] + 1;
            int sum = grid[c][d] - grid[c][b - 1] - grid[a - 1][d] + grid[a - 1][b - 1];
            if(sum == (c - a + 1) * (d - b + 1)) ++res;
        }
        return res;
    }
};

5227. K 次操作后最大化顶端元素

题目描述:给你一个下标从 \(0\) 开始的整数数组 \(nums\) ,它表示一个 栈 ,其中 \(nums[0]\) 是栈顶的元素。每一次操作中,你可以执行以下操作 之一 :

  • 如果栈非空,那么 删除 栈顶端的元素。
  • 如果存在 \(1\) 个或者多个被删除的元素,你可以从它们中选择任何一个,添加 回栈顶,这个元素成为新的栈顶元素。
    同时给你一个整数 \(k\) ,它表示你总共需要执行操作的次数。

请你返回 恰好 执行 \(k\) 次操作以后,栈顶元素的 最大值 。如果执行完 \(k\) 次操作以后,栈一定为空,请你返回 \(-1\)

思路:根据题意模拟即可,对于当前栈顶数字,若拿起后,剩余操作次数为奇数或者剩余操作次数大于\(2\)且栈的总元素数量不为\(1\),说明该元素可以在最终出现在栈顶。注意特判\(k + 1\)

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

参考代码:

class Solution {
public:
    int maximumTop(vector<int>& nums, int k) {
        int res = -1, n = nums.size();
        reverse(nums.begin() , nums.end());
        nums.push_back(0);
        reverse(nums.begin() , nums.end());
        for(int i = 1 ; i <= n ; ++i){
            int dx = k - i;
            if(dx % 2 == 1) res = max(res , nums[i]);
            else if(dx >= 2 && n != 1) res = max(res , nums[i]);
            
        }
        if(k < n) res = max(res , nums[k + 1]);
        return res;
    }
};

6032. 得到要求路径的最小带权子图

题目描述:给定\(n\)个点\(m\)条边的有向图,求删除一些边之后使得删边之后的图权值和最小,且\(s1,s2\)都可以到达\(dest\)。求最小权值和,若不能满足条件,返回\(-1\)

思路:定义\(dist_{i , j}\)表示从\(i\)出发到\(j\)的最短路径,那么答案为:

\[\mathop{min}\limits_{i = 0}^{n - 1}\;dist_{s1 , i} + dist_{s2 , i} + dist_{i , dest} \]

所以对\(s1,s2\)\(Dijkstra\),然后建立反向边以\(dest\)为起点跑\(Dijkstra\),然后枚举中间点取最小即可。

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

参考代码:

class Solution {
public:
    long long minimumWeight(int n, vector<vector<int>>& edges, int s1, int s2, int dest) {
        using PLI = pair<long long, int>;
        using PII = pair<int , int>;
        vector<vector<PII>>graph(n), regraph(n);
        vector<vector<int>>tr(n);
        for (auto& edge : edges) {
            int u = edge[0], v = edge[1], w = edge[2];
            graph[u].push_back({ v , w });
            regraph[v].push_back({u , w});
        }
        const long long MAXN = 0x3f3f3f3f3f3f3fll;
       
        auto Dijkstra = [](vector<vector<PII>>& graph ,vector<long long>& dist, int st, int n) {
            dist[st] = 0;
            priority_queue<PLI, vector<PLI>, greater<PLI>>heap;
            heap.push({ 0 , st });
            vector<bool>vis(n, false);
            while (!heap.empty()) {
                auto [dis, ver] = heap.top();
                heap.pop();
                if (vis[ver]) continue;
                vis[ver] = true;
                for (auto&& [v, w] : graph[ver]) {
                    if (dist[v] > w + dis) {
                        dist[v] = w + dis;
                        heap.push({ dist[v] , v });
                    }
                }
            }
        };
        vector<long long>d1(n, MAXN), d2(n , MAXN) , d3(n , MAXN);
        Dijkstra(graph , d1 , s1 , n);
        Dijkstra(graph , d2 , s2 , n);
        Dijkstra(regraph , d3 , dest , n);
        if(d3[s1] == MAXN || d3[s2] == MAXN) return -1;
        long long res = LLONG_MAX;
        for(int i = 0 ; i < n ; ++i){
            res = min(res , d1[i] + d2[i] + d3[i]);
        }
        return res;
    }
};
posted @ 2022-03-13 12:57  cherish-lgb  阅读(28)  评论(0编辑  收藏  举报