一题失眠!只有数据量上来了才知道谁在裸泳|刷题打卡

103 阅读2分钟

一、题目描述:

二、思路分析:

这道题看起来很简单,图嘛!

  1. 先设置二维数组,遍历边!
  2. 一个边上两个点,在二维数组所有和该点有关系的都加1,(x,y)只加一次1
  3. 遍历query,for循环二维数组算出超过query——i的个数

死的老惨了

但是其实题是做出来了的,那就需要逐步优化

  1. 二维数组如果是点对ab,那么每次循环都要对二维数组进行大量更新,我们设置一个一维数组,记录点旁边的边的个数,并将二维数组改为ab相连的边的个数,这么一改,省下了四个for循环

自鸣得意,提交!

还是超时

  1. 将二维数组改为一维数组,这样一个好处时从n^2变成了n*(n - 1)/2,我当然知道这个改动不大,但同时也可以对数组使用sort排序,原先的遍历计数改为了遇到比query[i]大的就退出,又省了一步

自鸣得意,提交!

还是超时

  1. 之前既然想到了sort,也就是出现了有序数组,不如就从遍历改为二分,n变logn! 自鸣得意,提交!

还是超时

我做双周赛时就想到了这些,其实离答案很近了,这也是我看完答案失眠的原因,希望读者做完题再往下看。

三、AC 代码:

class Solution {
public:
    vector<int> countPairs(int n, vector<vector<int>>& edges, vector<int>& queries) {
        vector<int> deg(n + 1, 0);
        
        int nEdges = edges.size();
        unordered_map<int, int> overlap;
        vector<vector<int>> distinctEdges; // 去除重边后的边数组,这样处理每个 query 时能少遍历几条边
        auto encode = [n](int a, int b) -> int {return max(a, b) * (n + 1) + min(a, b);};
        for (int i = 0; i < nEdges; i++) {
            int p = edges[i][0], q = edges[i][1];
            deg[p]++;
            deg[q]++;
            int idx = encode(p, q);
            if (overlap.find(idx) == overlap.end()) {
                distinctEdges.push_back({p, q});
            }
            overlap[idx]++;
        }

        vector<int> sortedDeg(deg.begin() + 1, deg.end());
        sort(sortedDeg.begin(), sortedDeg.end());
        
        int nQueries = queries.size();
        vector<int> ret(nQueries);
        for (int i = 0; i < nQueries; i++) {
            int l = 0, r = n - 1;
            int cnt = 0;
            while (l < n) {
                while (r > l && sortedDeg[l] + sortedDeg[r] > queries[i]) {
                    r--;
                }
                cnt += (n - max(l, r) - 1);
                l++;
            }

            for (int j = 0; j < distinctEdges.size(); j++) {
                int p = distinctEdges[j][0], q = distinctEdges[j][1];
                int idx = encode(p, q);
                if (deg[p] + deg[q] > queries[i] && deg[p] + deg[q] - overlap[idx] <= queries[i]) {
                    cnt--;
                }
            }
            ret[i] = cnt;
        }
        return ret;
    }
};



四、总结:

这个代码是那个题解的,我按这个代码写其实还是超时,他的优化基本就是把一个枚举点对改为枚举边,前面通过双指针求值。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情