1. 程式人生 > 實用技巧 >leetcode周賽220

leetcode周賽220

這場比賽的題都是老套路,但是由於太久沒刷題瘋狂寫bug……

目錄

比賽連結

傳送門

重新格式化電話號碼

思路

直接模擬

程式碼

class Solution {
public:
    string reformatNumber(string number) {
        string str, ans;
        for(auto s:number) {
            if(s == ' ' || s == '-') continue;
            str += s;
        }
        int n = str.length();
        for(int i = 0; i < n; i += 3) {
            if(n - i <= 4) {
                if(n - i != 4) {
                    while(i < n) {
                        ans += str[i];
                        ++i;
                    }
                } else {
                    for(int j = 0; j < 2; ++j) ans += str[i+j];
                    ans += '-';
                    i += 2;
                    for(int j = 0; j < 2; ++j) ans += str[i+j];
                }
                break;
            } else {
                for(int j = 0; j < 3; ++j) ans += str[i+j];
                ans += '-';
            }
        }
        return ans;
    }
};

刪除子陣列的最大得分

思路

記錄一下每個值上一次出現的位置,然後字首和計算答案。

程式碼

class Solution {
    map<int, int> pos;
public:
    int maximumUniqueSubarray(vector<int>& nums) {
        int n = nums.size(), ans = 0, pre = 0;
        vector<int> sum(n+1);
        for(int i = 0; i < n; ++i) {
            sum[i + 1] = sum[i] + nums[i];
            if(pos.count(nums[i])) {
                pre = max(pre, pos[nums[i]]);
            }
            ans = max(ans, sum[i+1] - sum[pre]);
            pos[nums[i]] = i + 1;
        }
        return ans;
    }
};

跳躍遊戲 VI

思路

滑動視窗,維護一個單調遞減的佇列。

程式碼

class Solution {
public:
    int maxResult(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> dp(n);
        deque<int> q;
        for(int i = 0; i < n; ++i) {
            while(!q.empty() && i - q.back() > k) {
                q.pop_back();
            }
            int val = 0;
            if(!q.empty()) val = dp[q.back()];
            dp[i] = val + nums[i];
            while(!q.empty() && dp[q.front()] < dp[i]) q.pop_front();
            q.push_front(i);
        }
        return dp[n-1];
    }
};

檢查邊長度限制的路徑是否存在

思路

將邊和查詢都按照權值從小到達排序,然後列舉每個查詢,將權值小於查詢邊權的所有邊加入到最小生成樹,判斷查詢的兩個端點是否聯通即可。

程式碼

class Solution {
    static const int maxn = 100000 + 7;
    struct edge {
        int u, v, w, id;
        bool operator < (const edge & x) const {
            return w < x.w;
        }
    }edge[maxn], query[maxn];
    int fa[maxn];

public:
    int find(int x) {
        return fa[x] == x ? x : fa[x] = find(fa[x]);
    }

    vector<bool> distanceLimitedPathsExist(int n, vector<vector<int>>& edgeList, vector<vector<int>>& queries) {
        int m = edgeList.size(), q = queries.size();
        for(int i = 0; i < m; ++i) {
            edge[i].u = edgeList[i][0], edge[i].v = edgeList[i][1];
            edge[i].w = edgeList[i][2];
        }
        for(int i = 0; i < q; ++i) {
            query[i].u = queries[i][0], query[i].v = queries[i][1];
            query[i].w = queries[i][2], query[i].id = i;
        }
        vector<bool> ans(q);
        sort(edge, edge + m);
        sort(query, query + q);
        for(int i = 0; i < n; ++i) fa[i] = i;
        int pos = 0;
        for(int i = 0; i < q; ++i) {
            while(pos < m && edge[pos].w < query[i].w) {
                int p1 = find(edge[pos].u), p2 = find(edge[pos].v);
                ++pos;
                if(p1 == p2) continue;
                fa[p1] = p2;
            }
            int p1 = find(query[i].u), p2 = find(query[i].v);
            if(p1 == p2) ans[query[i].id] = true;
            else ans[query[i].id] = false;
        }
        return ans;
    }
};