LeetCode第330场周赛

2023.1.29LeetCode第330场周赛

2549. 统计桌面上的不同数字

思路

题意是找出集合中相除余数为1的数,并加入集合,直至不能更新,求集合中数的数量
给定数nn - 1 != 1时,与n - 1相除余数为1,故[2, n]中的所有数都会被加入集合,数量为n - 1n = 1时特判

代码

class Solution {
public:
    int distinctIntegers(int n) {
        if (n == 1) return 1;
        return n - 1;
    }
};

2550. 猴子碰撞的方法数

思路

快速幂
只有当所有猴子同方向时不会碰撞,方法数为 2 n − 2 2^n - 2 2n2

代码

class Solution {
public:
    typedef long long ll;

    ll qmi(ll a, ll b, ll mod) {
        ll res = 1;
        while (b) {
            if (b & 1) res = res * a % mod;
            a = a * a % mod;
            b >>= 1;
        }
        return res;
    }

    int monkeyMove(int n) {
        ll mod = 1e9 + 7;
        return (qmi(2, n, mod) + mod - 2) % mod;
    }
};

2551. 将珠子放入背包中

思路

题意是将数组分为k段,即选择k - 1个分界线,每个分界线在计算时是相邻两个元素之和,第一个元素和最后一个元素每种方案都会选到,将所有的相邻两个元素和计算出来,求最大的k - 1和最小的k - 1个数之和的差为答案

代码

class Solution {
public:
    typedef long long ll;
    
    long long putMarbles(vector<int>& w, int k) {
        int n = w.size();
        if (n == 1) return 0;
        vector<ll> a;
        for (int i = 0; i < n - 1; i ++ )
            a.push_back(w[i] + w[i + 1]);
        sort(a.begin(), a.end());
        ll t1 = 0, t2 = 0;
        // 最大的k - 1个数
        for (int i = a.size() - 1; i >= a.size() - k + 1 && i >= 0; i -- )
            t1 += a[i];
        // 最小的k - 1个数
        for (int i = 0; i < k - 1 && i < a.size(); i ++ )
            t2 += a[i];
        return t1 - t2;
    }
};

2552. 统计上升四元组

思路

i < j < k < l i<j<k<l i<j<k<l,同时, n u m s [ i ] < n u m s [ k ] < n u m s [ j ] < n u m s [ l ] nums[i] < nums[k] < nums[j] < nums[l] nums[i]<nums[k]<nums[j]<nums[l]
数组范围允许使用双循环,枚举所有的jk,当nums[j] > nums[k]时,需要找到j左边小于nums[k]的数的数量和k右边大于nums[j]的数的数量,根据乘法原理求出答案,由于nums数组是一个排列,可以运用前缀和先预处理出目标数组lr来表示数量

代码

class Solution {
public:
    typedef long long ll;
    
    long long countQuadruplets(vector<int>& a) {
        int n = a.size();
        const int N = 4010;
        vector<vector<int>> l, r;
        l.resize(n, vector<int>(N));
        r.resize(n, vector<int>(N));
        for (int i = 0; i < n; i ++ ) {
            if (i)
                l[i] = l[i - 1];
            for (int j = a[i] + 1; j < N; j ++ )
                l[i][j] ++ ;
        }
        for (int i = n - 1; i >= 0; i -- ) {
            if (i < n - 1)
                r[i] = r[i + 1];
            for (int j = a[i] - 1; j >= 0; j -- )
                r[i][j] ++ ;
        }
        ll ans = 0;
        for (int i = 1; i < n; i ++ )
            for (int j = i + 1; j < n - 1; j ++ ) {
                if (a[i] > a[j]) {
                    ans += l[i - 1][a[j]] * r[j + 1][a[i]];
                }
            }
        return ans;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值