LeetCode刷题——第 72 场双周赛和第 281 场力扣周赛

第 72 场双周赛

5996. 统计数组中相等且可以被整除的数对

题目
给你一个下标从 0 开始长度为 n 的整数数组 nums 和一个整数 k ,请你返回满足 0 <= i < j < n ,nums[i] == nums[j] 且 (i * j) 能被 k 整除的数对 (i, j) 的 数目 。

示例 1:

输入:nums = [3,1,2,2,2,1,3], k = 2
输出:4
解释:
总共有 4 对数符合所有要求:

  • nums[0] == nums[6] 且 0 * 6 == 0 ,能被 2 整除。
  • nums[2] == nums[3] 且 2 * 3 == 6 ,能被 2 整除。
  • nums[2] == nums[4] 且 2 * 4 == 8 ,能被 2 整除。
  • nums[3] == nums[4] 且 3 * 4 == 12 ,能被 2 整除。

示例 2:

输入:nums = [1,2,3,4], k = 1
输出:0
解释:由于数组中没有重复数值,所以没有数对 (i,j) 符合所有要求。

提示:

1 <= nums.length <= 100
1 <= nums[i], k <= 100

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-equal-and-divisible-pairs-in-an-array
代码
遍历即可

class Solution {
public:
    int countPairs(vector<int>& nums, int k) {
        int ans=0;
        for(int i=0; i < nums.size()-1; i++){
            for(int j=i+1; j < nums.size(); j++){
                if(nums[i]==nums[j] && i * j % k == 0){
                    ans ++;
                }
            }
        }
        return ans;
    }
};

5997. 找到和为给定整数的三个连续整数

题目
给你一个整数 num ,请你返回三个连续的整数,它们的 和 为 num 。如果 num 无法被表示成三个连续整数的和,请你返回一个 空 数组。

示例 1:

输入:num = 33
输出:[10,11,12]
解释:33 可以表示为 10 + 11 + 12 = 33 。
10, 11, 12 是 3 个连续整数,所以返回 [10, 11, 12] 。

示例 2:

输入:num = 4
输出:[]
解释:没有办法将 4 表示成 3 个连续整数的和。

提示:

0 <= num <= 10^15

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-three-consecutive-integers-that-sum-to-a-given-number
代码
直接除3获取中间值,如果以中间值为基础的三维数之和为num返回3个值,否则返回空

class Solution {
public:
    vector<long long> sumOfThree(long long num) {
        long long mid = num / 3;
        if(mid-1 + mid + mid + 1 == num){
            return {mid-1, mid, mid+1};
        }
        return {};
    }
};

5998. 拆分成最多数目的偶整数之和

题目
给你一个整数 finalSum 。请你将它拆分成若干个 互不相同 的偶整数之和,且拆分出来的偶整数数目 最多 。

比方说,给你 finalSum = 12 ,那么这些拆分是 符合要求 的(互不相同的偶整数且和为 finalSum):(2 + 10) ,(2 + 4 + 6) 和 (4 + 8) 。它们中,(2 + 4 + 6) 包含最多数目的整数。注意 finalSum 不能拆分成 (2 + 2 + 4 + 4) ,因为拆分出来的整数必须互不相同。
请你返回一个整数数组,表示将整数拆分成 最多 数目的偶整数数组。如果没有办法将 finalSum 进行拆分,请你返回一个 空 数组。你可以按 任意 顺序返回这些整数。

示例 1:

输入:finalSum = 12
输出:[2,4,6]
解释:以下是一些符合要求的拆分:(2 + 10),(2 + 4 + 6) 和 (4 + 8) 。
(2 + 4 + 6) 为最多数目的整数,数目为 3 ,所以我们返回 [2,4,6] 。
[2,6,4] ,[6,2,4] 等等也都是可行的解。

示例 2:

输入:finalSum = 7
输出:[]
解释:没有办法将 finalSum 进行拆分。
所以返回空数组。

示例 3:

输入:finalSum = 28
输出:[6,8,2,12]
解释:以下是一些符合要求的拆分:(2 + 26),(6 + 8 + 2 + 12) 和 (4 + 24) 。
(6 + 8 + 2 + 12) 有最多数目的整数,数目为 4 ,所以我们返回 [6,8,2,12] 。
[10,2,4,12] ,[6,2,4,16] 等等也都是可行的解。

提示:

1 <= finalSum <= 10^10

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-split-of-positive-even-integers
分析
如果num是奇数,那么他不可能被拆成若干个偶数的和,直接返回空。如果num是偶数则一定存在若干个偶数和为num,这时我们递增地对偶数进行深度优先搜索即可,注意这里只要找到可行解即可,所以我们一旦找到合适的情况即可退出。在代码中用flag来表示是否已找到合适的情况。
代码

class Solution {
public:
    vector<long long> ans;
    bool flag = false;
    void dfs(long long num, long long start){
        if(num < 0){
            return;
        }
        if(num == 0){
            flag = true;
            return;
        }
        for(long long i=start; num && i <= num/2; i++){
            ans.push_back(i * 2);
            dfs(num - i * 2, i+1);
            if(flag){
                break;
            }
            ans.pop_back();
        }
    }
    vector<long long> maximumEvenSplit(long long finalSum) {
        if(finalSum % 2){
            return {};
        }
        for(long long i=1; finalSum && i <= finalSum/2; i++){
            ans.push_back(i * 2);
            dfs(finalSum - i * 2, i+1);
            if(flag){
                break;
            }
            ans.pop_back();
        }
        return ans;
    }
};

5999. 统计数组中好三元组数目

题目
给你两个下标从 0 开始且长度为 n 的整数数组 nums1 和 nums2 ,两者都是 [0, 1, …, n - 1] 的 排列 。

好三元组 指的是 3 个 互不相同 的值,且它们在数组 nums1 和 nums2 中出现顺序保持一致。换句话说,如果我们将 pos1v 记为值 v 在 nums1 中出现的位置,pos2v 为值 v 在 nums2 中的位置,那么一个好三元组定义为 0 <= x, y, z <= n - 1 ,且 pos1x < pos1y < pos1z 和 pos2x < pos2y < pos2z 都成立的 (x, y, z) 。

请你返回好三元组的 总数目 。

示例 1:

输入:nums1 = [2,0,1,3], nums2 = [0,1,2,3]
输出:1
解释:
总共有 4 个三元组 (x,y,z) 满足 pos1x < pos1y < pos1z ,分别是 (2,0,1) ,(2,0,3) ,(2,1,3) 和 (0,1,3) 。
这些三元组中,只有 (0,1,3) 满足 pos2x < pos2y < pos2z 。所以只有 1 个好三元组。

示例 2:

输入:nums1 = [4,0,1,3,2], nums2 = [4,1,0,2,3]
输出:4
解释:总共有 4 个好三元组 (4,0,3) ,(4,0,2) ,(4,1,3) 和 (4,1,2) 。

提示:

n == nums1.length == nums2.length
3 <= n <= 105
0 <= nums1[i], nums2[i] <= n - 1
nums1 和 nums2 是 [0, 1, …, n - 1] 的排列。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-good-triplets-in-an-array
分析
对nums1做映射,然后按照树状数组去做即可
代码

class Solution {
public:
	vector<int> tree;
    long long goodTriplets(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size();
        vector<int> pos(n);
        for (int i = 0; i < n; ++i) {
            pos[nums2[i]] = i;
        }

        long long ans = 0;
        tree.resize(n + 1);
        
        // 只需要在 [1, n-1) 范围内枚举 pos1_y 即可
        for (int i = 1; i < n - 1; ++i) {
            update(pos[nums1[i - 1]] + 1);
            int p = pos[nums1[i]];
            int t = query(p);
            ans += static_cast<long long>(t) * (n - i - p + t - 1);
        }

        return ans;
    }

    static int lowbit(int x) {
        return x & (-x);
    }

    void update(int x) {
        while (x < tree.size()) {
            ++tree[x];
            x += lowbit(x);
        }
    }

    int query(int x) {
        int ans = 0;
        while (x) {
            ans += tree[x];
            x -= lowbit(x);
        }
        return ans;
    }
};

第 281 场力扣周赛

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)
链接:https://leetcode-cn.com/problems/count-integers-with-even-digit-sum
代码
遍历查询即可

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)
链接:https://leetcode-cn.com/problems/construct-string-with-repeat-limit
分析
可以按从大到小的字母将所有出现的字母进行排序,然后使用双指针,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)
链接:https://leetcode-cn.com/problems/count-array-pairs-divisible-by-k
代码

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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾醒(AiXing-w)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值