1. 程式人生 > 其它 >LeetCode第 284 場周賽題解

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;
    }
};