返回顶部

LeetCode第 72 场双周赛题解

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

题目描述:给你一个长度为\(n\)的整数数组\(nums\),下标从\(0\)开始,问有多少下标\(i , j\)满足\(nums_i = nums_j , i \neq j , i *j \% k = 0\)

数据范围:\(1 \leq n \leq 100\)

思路:数据范围很小,直接暴力即可

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

参考代码:

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

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

题目描述:给你一个整数\(n\),让你把其分解成三个连续的整数,若不存在分解方案,返回空数组。

思路:根据题意模拟即可

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

参考代码:

class Solution {
public:
    vector<long long> sumOfThree(long long num) {
        vector<long long>res;
        if(num % 3 != 0) return res;
        long long dx = num / 3;
        for(long long i = dx - 1 ; i <= dx + 1 ; ++i) res.push_back(i);
        return res;
    }
};

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

题目描述:给你一个整数\(n\),让你将其分解成不同偶数之和,要返回分解之后元素最多的方案,若不存在方案,返回空数组。

思路:显然奇数时不存在方案,特判。对于偶数,从\(2\)开始枚举,每次加\(2\),若剩余的数字减去当前枚举的数字后大于当前枚举的数字,那么把当前枚举的数字放入答案,剩余数字减去当前数字,否则将剩余数字放入答案,结束循环。

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

参考代码:

class Solution {
public:
    vector<long long> maximumEvenSplit(long long num) {
        vector<long long> res;
        if(num & 1) return res;
        long long cur = 2;
        while(num >= cur){
            if(num - cur > cur){
                res.push_back(cur);
                num -= cur;
                cur += 2;
            }
            else{
                res.push_back(num);
                break;
            }
        }
        return res;
    }
};

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

题目描述:给你两个长度为\(n\)的排列\(P_1 , P_2\),统计满足下列条件的三元组的数量:

  • \(P_1[pos_{u1}] = P_2[pos_{u2}]\)
  • \(P_1[pos_{v1}] = P_2[pos_{v2}]\)
  • \(P_1[pos_{w3}] = P_2[pos_{w3}]\)
  • \(pos_{u1} < pos_{v1} < pos_{w1}\)
  • \(pos_{u2} < pos_{v2} < pos_{w2}\)

思路:比较老套路的题,将其中一个排列映射成一个有序排列\(1...n\) 。那么原题就转化成对于另一个排列,其中满足:

  • \(pos_x < pos_y < pos_z\)
  • \(P_1[pos_x] < P_1[pos_y] < P_1[pos_z]\)

的三元组的数量。这也是一个经典题目,可以参考P1637 三元上升子序列。上述的转化思想可以参考P1439 【模板】最长公共子序列 。用两个树状数组或者线段树维护一下即可。

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

参考代码:

class Solution {
    
public:
    long long goodTriplets(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size();
        vector<int>f(n + 1 , 0);
        for(int i = 1 ; i <= n ; ++i){
            f[nums2[i - 1]] = i;
        }
        for(auto& num : nums1) num = f[num];
        long long res = 0;
        vector<int>tr1(n + 1 , 0) , tr2(n + 1 , 0);
        auto lowbit = [](int x){return x & -x;};
        auto add = [&](vector<int>& tr , int idx , int val)->void{
            while(idx <= n){
                tr[idx] += val;
                idx += lowbit(idx);
            }
            return ;
        };
        auto getsum = [&](vector<int>& tr , int idx)->int{
            int ans = 0;
            while(idx){
                ans += tr[idx];
                idx -= lowbit(idx);
            }
            return ans;
        };
        for(auto num : nums1) add(tr1 , num , 1);
        for(int i = 1 ; i <= n ; ++i){
            int val = nums1[i - 1];
            add(tr1 , val , -1);
            int lr = getsum(tr2 , val), rs = n - i - getsum(tr1 , val - 1);
            res += 1ll * lr * rs;
           
            add(tr2 , val , 1);
        }
        return  res;
    }
};
posted @ 2022-02-20 10:22  cherish-lgb  阅读(41)  评论(1编辑  收藏  举报