力扣:第 315 场周赛

83 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第18天,点击查看活动详情

力扣——第 315 场周赛

6204. 与对应负数同时存在的最大正整数 - 力扣(LeetCode)

问题解析

遍历数组,哈希表记录每个元素的出现次数,当遇到正数时看它的负数有没有被哈希表记录过,如果记录过就把这个数存下来,维护最大值。

但是数组是无序的,所以有可能遇到遍历到正数时还没遇到它负数的情况,所以我们可以先对数组排个序再遍历;或者先遍历一次只记录负数,再遍历一次只记录正数。

AC代码

class Solution {
public:
    int findMaxK(vector<int>& nums) {
        unordered_map<int,int>mymap;
        sort(nums.begin(),nums.end());
        int mx=-1;
        for(auto i:nums)
        {
            if(i>0)c
            {
                if(mymap[-1*i]!=0)mx=max(mx,i);
            }
            mymap[i]=1;
        }
        return mx;
    }
};

6205. 反转之后不同整数的数目 - 力扣(LeetCode)

问题解析

哈希表记录每个数的出现次数。

每遍历到一个数,就把这个数反转过来,然后再用哈希表记录下来。

最后返回哈希表的大小即可。

AC代码

class Solution {
public:
    int countDistinctIntegers(vector<int>& nums) {
        unordered_map<int,int>mymap;
        int n=nums.size();
        for(int i=0;i<n;i++)
        {
            mymap[nums[i]]=1;
            int x=nums[i],ans=0;
            while(x)
            {
                ans*=10;
                ans+=x%10;
                x/=10;
            }
            mymap[ans]=1;
        }
        return mymap.size();
    }
};

6219. 反转之后的数字和 - 力扣(LeetCode)

问题解析

注意到num最大只有1e5,而且可以知道,如果有个数能满足题目的条件,那么哪个数肯定不会大于num。

所以我们可以从0开始枚举数x,每次再把x翻转过来记作y,判断x+y是否等于num。

有一个能满足就返回true。如果都满足不了就输出false。

复杂度为:O(n*len(n))

AC代码

class Solution {
public:
    bool sumOfNumberAndReverse(int num) {
        for(int i=0;i<=num;i++)
        {
            int x=i,ans=0;
            while(x)
            {
                ans*=10;
                ans+=x%10;
                x/=10;
            }
            if(ans+i==num)return true;
        }
        return false;
    }
};

6207. 统计定界子数组的数目 - 力扣(LeetCode)

问题解析

双指针+优先队列。

我们用两个优先队列minpos和maxpos来存储遍历过程中,值等于minK和值等于maxK的元素的下标。

  • 如果当前数在minK和maxK的范围中,右指针r继续移动。
  • 如果当前数不在minK和maxK的范围中,则开始移动左指针l,同时计算一下每个数作为左边界能提供的贡献。

如果minpos和maxpos都不为空,说明当前l到r-1的数组是满足题目要求的。

则当前左指针所能提供的贡献就为:r-max(minpos.top(),maxpos.top());

因为要求数组中同时有minK和maxK,所以数组的右边界最小是他俩中最大的那个下标,然后左指针从这个下标开始到达r指针的这一段距离都可以是左指针提供的贡献。例如:

num={4,2,3,1,4,5,2,7} ,minK=1 ,maxK=5
                                {4  2  3  1  4  5  2  7}
对于每个左边界,他们提供的数组有: 4  2  3  1  4  5  2
                                 4  2  3  1  4  5
                                    2  3  1  4  5  2
                                    2  3  1  4  5
                                       3  1  4  5  2
                                       3  1  4  5
                                          1  4  5  2
                                          1  4  5

当左指针指向的下标等于minpos.top()或maxpos.top()时,我们将它弹出,然后继续计算。

直到其中有一个队列为空时,因为当前r是不在minK和maxK范围中的,所以当我们把r+1,再直接将l移动到r的位置上,同时情况两个优先队列。双指针再继续移动。

AC代码

class Solution {
public:
    long long countSubarrays(vector<int>& nums, int minK, int maxK) {
        long long n = nums.size(), l = 0, r = 0, res = 0;
        priority_queue<int, vector<int>, greater<int>>mnpos, mxpos;
        while (r <= n)
        {
            if (r == n || nums[r] > maxK || nums[r] < minK)
            {
                while (l < r)
                {
                    if (mnpos.empty() || mxpos.empty())break;
                    int x = max(mnpos.top(), mxpos.top());
                    res += r - x;
                    if (mnpos.top() == l)mnpos.pop();
                    if (mxpos.top() == l)mxpos.pop();
                    l++;
                }
                while (!mnpos.empty())mnpos.pop();
                while (!mxpos.empty())mxpos.pop();
                r++;
                l=r;
                continue;
            }
            if (nums[r] == minK)mnpos.push(r);
            if (nums[r] == maxK)mxpos.push(r);
            r++;
        }
        return res;
    }
};