Leetcode周赛375总结

Q1 统计已测试设备

  • 题目链接

  • 解题思路:

    • 从左向右遍历
    • 用一个变量cnt记录在当前位置左侧已经有多少个已测试设备
    • 在当前位置,检查max(batteryPercentages[i] - cnt, 0)是否大于0,如果大于0,更新cnt
  • 解题代码:


class Solution {
public:
    int countTestedDevices(vector<int>& batteryPercentages) {
        int cnt = 0;
        for(auto bp : batteryPercentages)
        {
            int temp = max(bp - cnt, 0);
            if(temp > 0)
                cnt += 1;
        }
        return cnt;
    }
};

Q2 双横幂运算

  • 题目链接

  • 解题思路:

    • 数据范围并不大
    • 利用迭代模拟求幂操作即可
  • 解题代码:


class Solution {
public:
    vector<int> getGoodIndices(vector<vector<int>>& variables, int target) {
        vector<int> ans;
        int n = variables.size();
        for(int i = 0; i < n; i++)
        {
            int a = variables[i][0], b = variables[i][1], c = variables[i][2], m = variables[i][3];
            int temp = 1;
            for(int j = 1; j <= b; j++)
                temp = temp * a % 10;
            a = temp;
            for(int j = 1; j < c; j++)
                temp = temp * a % m;
            if(temp % m == target)
                ans.push_back(i);
        }
        return ans;
    }
};

Q3 统计最大元素出现至少K次的子数组

  • 题目链接

  • 解题思路:

    • 先找到数组中的最大元素
    • 滑动窗口,向右移动right指针,同时向右移动left指针,直到满足[left, right]中最大元素恰好出现k次,并且left位置的元素刚好是最大元素,此时可以组成left+1个满足条件的子数组,更新到答案中
  • 解题代码:


class Solution {
public:
    long long countSubarrays(vector<int>& nums, int k) {
        long long ans = 0;
        int mx = *max_element(nums.begin(), nums.end());
        int left = 0, right = 0;
        int n = nums.size();
        int cnt = 0;
        while(right < n)
        {
            if(nums[right] == mx)
                cnt += 1;
            while(cnt > k || (cnt == k && nums[left] != mx))
            {
                if(nums[left] == mx)
                    cnt -= 1;
                left += 1;
            }
            if(cnt == k)
                ans += left + 1;
            right += 1;
        }
        return ans;
    }
};

Q4 统计好分割方案的数目

  • 题目链接

  • 解题思路:

    • 首先统计数组中各元素的出现位置
    • 对于出现多次的元素,其第一次出现与其最后一次出现构成一个区间,该区间内的数必须分在同一组
    • 合并上述的区间
    • 这些合并后的区间只可以整体一组
    • 假设两个区间之间有m个数,这m个数共有2^(m-1)种分割法
    • 将两区间之间的数也看作整体,假设一共有n个整体,这n个整体共有2^(n-1)种方法
  • 解题代码:


class Solution {
public:
    const int MOD = 1e9 + 7;
    long long myPow(long long a, int n)
    {
        if(n == 0)
            return 1;
        if(n & 1)
            return a * myPow(a, n-1) % MOD;
        long long temp = myPow(a, n/2);
        return temp * temp % MOD;
    }
    int numberOfGoodPartitions(vector<int>& nums) {
        unordered_map<int, vector<int>> um;
        int n = nums.size();
        for(int i = 0; i < n; i++)
            um[nums[i]].push_back(i);
        vector<pair<int, int>> intervals;
        for(auto &it : um)
        {
            vector<int>& idxs = it.second;
            if(idxs.size() < 2)
                continue;
            intervals.push_back({idxs[0], idxs.back()});
        }
       
        //合并区间
        int len = intervals.size();
        if(len == 0)//没有区间
            return myPow(2, n-1);
        sort(intervals.begin(), intervals.end());
        int curLeft = intervals[0].first, curRight = intervals[0].second;
        vector<pair<int, int>> newIntervals;
        for(int i = 1; i < len; i++)
        {
            auto [l, r] = intervals[i];
            if(l < curRight)//合并
            {    
                curRight = max(r, curRight);
                continue;
            }
            //不合并
            newIntervals.push_back({curLeft, curRight});
            curLeft = l;
            curRight = r;
        }
        newIntervals.push_back({curLeft, curRight});
       
        //计算方案数
        long long ans = 1;
        int left = 0;
        int cnt = 0;
        for(auto [l, r] : newIntervals)
        {
            cnt += 1;
            if(l != left)
            {
                ans = ans * myPow(2, l-left-1) % MOD;
                cnt += 1;
            }
            left = r + 1;
        }
        if(n != left)
        {
            ans = ans * myPow(2, n-left-1) % MOD;
            cnt += 1;
        }
        ans = ans * myPow(2, cnt-1) % MOD;
        return ans;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值