LeetCode周赛总结——LeetCode第 281 场周赛

190 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

6012. 统计各位数字之和为偶数的整数个数

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

正整数的 各位数字之和 是其所有位上的对应数字相加的结果。

示例 1:

输入:num = 4 输出:2 解释: 只有 2 和 4 满足小于等于 4 且各位数字之和为偶数。

示例 2:

输入:num = 30 输出:14 解释: 只有 14 个整数满足小于等于 30 且各位数字之和为偶数,分别是: 2、4、6、8、11、13、15、17、19、20、22、24、26 和 28 。

提示:

1 <= num <= 1000

来源:力扣(LeetCode)

链接:leetcode-cn.com/problems/co…

代码

遍历查询即可

class Solution {
public:
    bool get(int n){
        int c=0;
        while(n){
            c+=n % 10;
            n /=10;
        }
        return c % 2 == 0;
    }
    int countEven(int num) {
        int ans=0;
        for(int i=2; i <= num; i++){
            if(get(i)){
                ans++;
            }
        }
        return ans;
    }
};

6013. 合并零之间的节点

给你一个链表的头节点 head ,该链表包含由 0 分隔开的一连串整数。链表的 开端 和 末尾 的节点都满足 Node.val == 0 。

对于每两个相邻的 0 ,请你将它们之间的所有节点合并成一个节点,其值是所有已合并节点的值之和。然后将所有 0 移除,修改后的链表不应该含有任何 0 。

返回修改后链表的头节点 head 。

示例 1:

输入:head = [0,3,1,0,4,5,2,0] 输出:[4,11] 解释: 上图表示输入的链表。修改后的链表包含:

  • 标记为绿色的节点之和:3 + 1 = 4
  • 标记为红色的节点之和:4 + 5 + 2 = 11

示例 2:

输入:head = [0,1,0,3,0,2,2,0] 输出:[1,3,4] 解释: 上图表示输入的链表。修改后的链表包含:

  • 标记为绿色的节点之和:1 = 1
  • 标记为红色的节点之和:3 = 3
  • 标记为黄色的节点之和:2 + 2 = 4

提示:

列表中的节点数目在范围 [3, 2 * 105] 内 0 <= Node.val <= 1000 不 存在连续两个 Node.val == 0 的节点 链表的 开端 和 末尾 节点都满足 Node.val == 0

分析

链表遍历题,如果当前的结点不为空并且不为0相加,如果为0新建新的结点,并令结点值为0,注意要判断最后一个0结点的值的情况

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeNodes(ListNode* head) {
        ListNode* newhead = new ListNode;
        if(!head){
            return NULL;
        }
        while(head && head->val==0){
            head = head->next;
        }
        if(!head){
            return NULL;
        }
        ListNode* t=newhead, * last;
        t->val = 0;
        while(head){
            if(head->val){
                t->val += head->val;
            }else{
                ListNode* tmp = new ListNode;
                tmp->val=0;
                last=t;
                t->next = tmp;
                t = t->next;
            }
            head = head->next;
        }
        if(last && !t->val){
            last->next = NULL;
        }
        return newhead;
    }
};

6014. 构造限制重复的字符串

给你一个字符串 s 和一个整数 repeatLimit ,用 s 中的字符构造一个新字符串 repeatLimitedString ,使任何字母 连续 出现的次数都不超过 repeatLimit 次。你不必使用 s 中的全部字符。

返回 字典序最大的 repeatLimitedString 。

如果在字符串 a 和 b 不同的第一个位置,字符串 a 中的字母在字母表中出现时间比字符串 b 对应的字母晚,则认为字符串 a 比字符串 b 字典序更大 。如果字符串中前 min(a.length, b.length) 个字符都相同,那么较长的字符串字典序更大。

示例 1:

输入:s = "cczazcc", repeatLimit = 3 输出:"zzcccac" 解释:使用 s 中的所有字符来构造 repeatLimitedString "zzcccac"。 字母 'a' 连续出现至多 1 次。 字母 'c' 连续出现至多 3 次。 字母 'z' 连续出现至多 2 次。 因此,没有字母连续出现超过 repeatLimit 次,字符串是一个有效的 repeatLimitedString 。 该字符串是字典序最大的 repeatLimitedString ,所以返回 "zzcccac" 。 注意,尽管 "zzcccca" 字典序更大,但字母 'c' 连续出现超过 3 次,所以它不是一个有效的 repeatLimitedString 。

示例 2:

输入:s = "aababab", repeatLimit = 2 输出:"bbabaa" 解释: 使用 s 中的一些字符来构造 repeatLimitedString "bbabaa"。 字母 'a' 连续出现至多 2 次。 字母 'b' 连续出现至多 2 次。 因此,没有字母连续出现超过 repeatLimit 次,字符串是一个有效的 repeatLimitedString 。 该字符串是字典序最大的 repeatLimitedString ,所以返回 "bbabaa" 。 注意,尽管 "bbabaaa" 字典序更大,但字母 'a' 连续出现超过 2 次,所以它不是一个有效的 repeatLimitedString 。

提示:

1 <= repeatLimit <= s.length <= 105 s 由小写英文字母组成

来源:力扣(LeetCode)

链接:leetcode-cn.com/problems/co…

分析

可以按从大到小的字母将所有出现的字母进行排序,然后使用双指针,left指针表示当前所处的位置,right来表示当left位置不满足要求时可互换的位置

代码

class Solution {
public:
    string repeatLimitedString(string s, int repeatLimit) {
        unordered_map<int, int> freq;
        for (char ch: s) {
            ++freq[ch];
        }
        
        string ans;
        ans.reserve(s.size());
        for (char ch = 'z'; ch >= 'a'; --ch) {
            for (int i = 0; i < freq[ch]; ++i) {
                ans.push_back(ch);
            }
        }
        
        int cnt = 1;

        for (int left = 1, right = 2; left < ans.size(); ++left) {
            if (ans[left - 1] != ans[left]) {
                cnt = 1;
            }
            else {
                ++cnt;
                if (cnt > repeatLimit) {
                    right = max(right, left + 1);
                    while (right < ans.size() && ans[left] == ans[right]) {
                        ++right;
                    }
                    if (right < s.size()) {
                        swap(ans[left], ans[right]);
                        cnt = 1;
                    }
                    else {
                        ans.erase(ans.begin() + left, ans.end());
                        break;
                    }
                }
            }
        }
        
        return ans;
    }
};

6015. 统计可以被 K 整除的下标对数目

给你一个下标从 0 开始、长度为 n 的整数数组 nums 和一个整数 k ,返回满足下述条件的下标对 (i, j) 的数目:

0 <= i < j <= n - 1 且 nums[i] * nums[j] 能被 k 整除。

示例 1:

输入:nums = [1,2,3,4,5], k = 2 输出:7 解释: 共有 7 对下标的对应积可以被 2 整除: (0, 1)、(0, 3)、(1, 2)、(1, 3)、(1, 4)、(2, 3) 和 (3, 4) 它们的积分别是 2、4、6、8、10、12 和 20 。 其他下标对,例如 (0, 2) 和 (2, 4) 的乘积分别是 3 和 15 ,都无法被 2 整除。

示例 2:

输入:nums = [1,2,3,4], k = 5 输出:0 解释:不存在对应积可以被 5 整除的下标对。

提示:

1 <= nums.length <= 10^5 1 <= nums[i], k <= 10^5

来源:力扣(LeetCode)

链接:leetcode-cn.com/problems/co…

代码

class Solution {
public:
    long long coutPairs(vector<int> &nums, int k) {
        vector<int> divisors; 
        for (int d = 1; d * d <= k; ++d) { // 预处理 k 的所有因子
            if (k % d == 0) {
                divisors.push_back(d);
                if (d * d < k) divisors.push_back(k / d);
            }
        }
        long long ans = 0;
        unordered_map<int, int> cnt;
        for (int v : nums) {
            ans += cnt[k / gcd(v, k)];
            for (int d : divisors)
                if (v % d == 0) ++cnt[d];
        }
        return ans;
    }
};