返回顶部

LeetCode第 281 场周赛题解

第 281 场周赛 - 力扣

T1

题目描述:给你一个正整数 \(num\) ,请你统计并返回 小于或等于 \(num\) 且各位数字之和为 偶数 的正整数的数目。

数据范围:\(1 \leq num \leq 1000\)

思路:数据范围很小,暴力枚举即可。

时间复杂度:\(O(nlog_{10}n)\)

参考代码:

class Solution {
public:
    int countEven(int num) {
        int res = 0;
        for(int i = 2 ; i <= num ; ++i){
            int j = i , sum = 0;
            while(j){
                sum += j % 10;
                j /= 10;
            }
            res += !(sum & 1);
        }
        return res;
    }
};

T2

题目描述:给你一个链表的头节点 head ,该链表包含由 0 分隔开的一连串整数。链表的 开端 和 末尾 的节点都满足 Node.val == 0 。对于每两个相邻的 0 ,请你将它们之间的所有节点合并成一个节点,其值是所有已合并节点的值之和。然后将所有 0 移除,修改后的链表不应该含有任何 0 。返回修改后链表的头节点 head

思路:根据题意模拟即可

时间复杂度:\(O(n)\)

参考代码:

class Solution {
public:
    ListNode* mergeNodes(ListNode* head) {
        vector<int> st;
        ListNode* p = head;
        while(p != nullptr){
            int dx = p->val;
            p = p->next;
            if(dx == 0) st.push_back(dx);
            else{
                if(st.back() == 0) st.push_back(dx);
                else st[st.size() - 1] += dx;
            }
        }
        int n = st.size();
        for(int i = 1 ; i < n ; i += 2){
            if(i == 1) p = new ListNode(st[i] , nullptr);
            else p->next = new ListNode(st[i] , nullptr), p = p->next;
            if(i == 1) head = p;
        }
        return head;
    }
};

T3

题目描述:使用给定的字符构造一个字典序最大的字符串,满足连续出现的相同字符的数量不超过阈值。

思路:根据题意,模拟加贪心即可

时间复杂度:\(O(n)\)

参考代码:

class Solution {
public:
    string repeatLimitedString(string s, int rp) {
        string res;
        vector<int>cnt(26 , 0);
        for(auto& c : s) cnt[c - 'a']++;
        for(int i = 25 ; i >= 0 ; --i){
            if(cnt[i] == 0) continue;
            for(int j = 1 ; j <= min(rp , cnt[i]) ; ++j) res += (char)(i + 'a');
            cnt[i] -= min(cnt[i] , rp);
            if(cnt[i] == 0) continue;
            int idx = -1;
            for(int j = i - 1 ; j >= 0 ; --j){
                if(cnt[j] == 0) continue;
                idx = j;
                break;
            }
            if(idx == -1) break;
            --cnt[idx];
            res += (char)(idx + 'a');
            ++i;
        }
        return res;
    }
};

T4

题目描述:给你一个长度为\(n\)的数组\(nums\),和一个整数\(k\),求满足以下条件的数对个数:

  • $ 1\leq i < j \leq n$
  • \(nums_i * nums_j\;mod\;k\; = \;0\)

思路:根据题意容易知道\(gcd(nums_i , k) * gcd(nums_j , k)\;mod\;k\;=\;0\)。故我们可以先将\(gcd(nums_i , k) , 1 \leq i \leq n\)求出来,存储到桶中。然后考虑到\(gcd(nums_i , k)\)一定在\(k\)的因子中,所以我们枚举\(k\)的所有因子,若两个因子的乘积能被\(k\)整除,那么就将其对应数量相乘。注意到若\(nums_i * nums_i\;mod\;k\;=\;0\),那么会对答案有重复贡献,在预处理时应\(-1\),最终返回其统计值的一半即可。

时间复杂度:\(O(nlogn)\)

参考代码:

class Solution {
public:
    long long coutPairs(vector<int>& nums, int k) {
        long long res = 0;
        vector<int>cnt(k + 1 , 0);
        for(auto num : nums) {
            if(1ll * num * num % k == 0)--res;
            int gd = gcd(num , k);
            ++cnt[gd];
        }
        vector<int>a;
        for(int i = 1 ; i * i <= k ; ++i){
            if(k % i != 0) continue;
            a.push_back(i);
            if(i != k / i) a.push_back(k / i);
        }
        sort(a.begin() , a.end());
        for(auto i : a){
            for(auto j : a){
                if(1ll * i * j % k == 0) res += 1ll * cnt[i] * cnt[j];
            }
        }
        return res >> 1;
    }
};
posted @ 2022-02-20 12:51  cherish-lgb  阅读(48)  评论(1编辑  收藏  举报