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;
    }
};
posted @ 2020-12-20 12:03  Dillonh  阅读(122)  评论(1编辑  收藏  举报