Weekly Contest 119

文章目录

    • 1) 前言
    • 2) 973. 最接近原点的 K 个点
    • 3) 974. 和可被 K 整除的子数组
    • 4) 975. 奇偶跳
    • 5) 976. 三角形的最大周长

1) 前言

半个学期转瞬即逝,项目还处在初级阶段,我却已经无比挣扎,以至于做任何别的事情都显得兴致不大啦。薄弱的实战能力让我做什么事情都束手束脚,有心无力。只能在这冬日抽出这须臾时光,写写不知多久前的contest总结啦。

2) 973. 最接近原点的 K 个点

传送门:https://leetcode-cn.com/problems/k-closest-points-to-origin/

//先计算所有的点到(0,0)的距离dis,然后对距离升序,小于dis[K-1]的点(X个)必然包含在最终的答案,再找出(K-X)个距离为dis[K-1]的点即可
class Solution {
public:
    vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
        vector<int> disPow, tmpDis;
        for(auto point: points) {
            disPow.push_back(point[0]*point[0] + point[1]*point[1]);
        }
        tmpDis = disPow;
        sort(tmpDis.begin(), tmpDis.end());
        
        vector<vector<int>> ans;
        int cnt = 0;
        for(int i = 0; i < disPow.size(); i++) {
            if(disPow[i] < tmpDis[K-1]) {
                ans.push_back(points[i]);
                cnt++;
            }
        }
        for(int i = 0; i < disPow.size(); i++) {
            if(disPow[i] == tmpDis[K-1]) {
                ans.push_back(points[i]);
                if(++cnt == K) break;
            }
        }
        return ans;
    }
};

3) 974. 和可被 K 整除的子数组

传送门:https://leetcode-cn.com/problems/subarray-sums-divisible-by-k/

/*
prefix表示前缀和,cntX是prefix中modulo K为X的个数,
ans为C(cntX, 2)的求和
*/
class Solution {
public:
    int subarraysDivByK(vector<int>& A, int K) {
        vector<int> cntX(K); //不用hashmap,节省空间
        cntX[0] = 1;
        
        int prefix = 0;
        int ans = 0;
        for(auto a : A) {
            prefix = (prefix + a%K+K) % K;//余数指向[0,K)
            ans += cntX[prefix]++; //组合数变成累加和
        }
        return ans;
    }
};

4) 975. 奇偶跳

传送门:https://leetcode-cn.com/problems/odd-even-jump/

/*
对排序后的{A[i], i}进行单调栈(monotonic stack)操作得到A中所有元素oddNext以及evenNext,
然后基于oddNext和evenNext逆时针扫描A可得evenReach和oddReach,最后统计A中的oddReach为true的个数

oddReach/evenReach: 从某位置jump是odd/even时可否到达尾下标
oddNext/evenNext: 从某位置jump是odd/even时到达的下一位置
*/
struct Node{
    int i,v;  
};
class Solution {
public:
    int oddEvenJumps(vector<int>& A) {
        stack<int> S;
        int lenA = A.size();
        Node nodes[20005];
        int oddNext[20005], evenNext[20005];
        memset(oddNext, -1, sizeof(oddNext));
        memset(evenNext, -1, sizeof(evenNext));
        oddNext[lenA-1] = evenNext[lenA-1] = lenA-1; //不必要
        
        //get oddNext & evenNext
        //升序nodes & 降序nodes
        for(int i = 0; i < lenA; i++) {
            nodes[i].i = i;
            nodes[i].v = A[i];
        }
        sort(nodes, nodes+lenA, cmp1);
        for(int i = 0; i < lenA; i++) {
            while(!S.empty()) {
                if(S.top() < nodes[i].i) { //
                    oddNext[S.top()] = nodes[i].i;
                    S.pop();
                }
                else break;
            }
            S.push(nodes[i].i);
        }
        while(!S.empty()) S.pop(); //
        sort(nodes, nodes+lenA, cmp2); 
        for(int i = 0; i < lenA; i++) {
            while(!S.empty()) {
                if(S.top() < nodes[i].i) {  //
                    evenNext[S.top()] = nodes[i].i;
                    S.pop();
                }
                else break;
            }
            S.push(nodes[i].i);
        }
        // for(int i = 0; i < lenA; i++) {
        //     cout << "oddNext" << '[' << i << "]=" << oddNext[i] << '\n';
        //     cout << "evenNext" << '[' << i << "]=" << evenNext[i] << '\n';
        // }
        //get evenReach & oddReach
        bool oddReach[20005]={false}, evenReach[20005]={false};
        oddReach[lenA-1] = evenReach[lenA-1] = true;
        for(int i = lenA-2; i >= 0; i--) {
            if(oddNext[i] != -1 && evenReach[oddNext[i]]) oddReach[i] = true;
            if(evenNext[i] != -1 && oddReach[evenNext[i]]) evenReach[i] = true;
        }
        
        //统计oddReach
        int ans = 0;
        for(int i = 0; i < lenA; i++) {
            if(oddReach[i]) ans++;
        }
        return ans;
    }
    //add static, 否则报error:invalid use of non-static member function
    static bool cmp1(const Node& node1, const Node& node2) {
        if(node1.v < node2.v) return true;
        else if(node1.v == node2.v) {
            if(node1.i < node2.i) return true;
            else return false;
        }
        else return false;
    }
    
    static bool cmp2(const Node& node1, const Node& node2) {
        if(node1.v < node2.v) return false;
        else if(node1.v == node2.v) {
            if(node1.i < node2.i) return true;
            else return false;
        }
        else return true;
    }
};

5) 976. 三角形的最大周长

传送门:https://leetcode-cn.com/problems/largest-perimeter-triangle/

//贪心
class Solution {
public:
    // bool cmp(int a, int b) { //降序
    //     return a > b;
    // }
    int largestPerimeter(vector<int>& A) {
        vector<int> T = A;
        sort(T.rbegin(), T.rend()); //反向迭代
        // cout << T[0] << '\n';
        for(int i = 0; i < T.size()-2; i++) {
            if(T[i]-T[i+1] < T[i+2]) return T[i]+T[i+1]+T[i+2];
        }
        return 0;
    }
    
};

你可能感兴趣的:(LeetCode,贪心,单调栈,前缀和)