与对应负数同时存在的最大正整数&&反转之后不同整数的数目&&反转之后的数字和&&统计定界子数组的数目

101 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情

[2441. 与对应负数同时存在的最大正整数]

leetcode.cn/problems/la…

image-20221018220837160


做法1: 将数组排成降序,然后插入到哈希表当中, 然后遍历数组,第一个可以被找到有相反数的就是最大的

class Solution {
public:
    int findMaxK(vector<int>& nums) {
       sort(nums.begin(),nums.end(),greater<int>());//排降序, 默认是升序
       unordered_set<int> us(nums.begin(),nums.end());
       for(auto& x: nums)
       {
           if(us.find(-x)!=us.end())//第一个找到有相反数的,就是当前最大的正整数
           {
               return x;
           }
       }
       return -1;
    }
};

做法2:直接用原数组构造哈希表,然后遍历原数组,定义一个遍历res记录"最大正整数", 不断更新,最后返回res

class Solution {
public:
    int findMaxK(vector<int>& nums) {
        unordered_set<int> us(nums.begin(),nums.end());
        int res = -1;//如果不存在这样的整数,返回-1
        for(auto& x:nums)
        {
            if(x >0 && us.count(-x)) //要保证x是正数!然后找它的相反数是否在哈希表当中
            {
                res = max(res,x);
            }
        }
        return res;
    }
};

[2442. 反转之后不同整数的数目]

leetcode.cn/problems/co…

image-20221018221459235


做法1:自己实现反转数字的函数,把原数组和反转之后的元素放到哈希表当中,最后返回哈希表的元素个数

class Solution {
public:
    unordered_set<int> us;
    //反转整数
    void reverse(int n)
    {
        int sum = 0;
        while(n)
        {
            sum  = sum*10 + n%10;
            n/=10;
        }
        us.insert(sum);//插入到哈希表当中
    }
    int countDistinctIntegers(vector<int>& nums) {
        for(auto& x:nums)
        {
            us.insert(x);
            reverse(x);
        }
        return us.size();
    }
};

做法2:利用string,把数字转为字符串,然后反转

class Solution {
public:
    int countDistinctIntegers(vector<int>& nums) {
        unordered_set<int> hash;
        for(auto& x:nums)
        {
            hash.insert(x);
            string s = to_string(x);//数字->字符串
            reverse(s.begin(),s.end());//反转数字
            //hash.insert(stoi(s)); //字符串->数字插入到哈希表
            hash.insert(atoi(s.c_str()));
        }
        return hash.size();
    }
};

[2443. 反转之后的数字和]

leetcode.cn/problems/su…

image-20221018221836618

某个数A+ 其反转之后的数B = num, A和B肯定都是<=num的,而且num的范围不大,所以我们可以直接暴力枚举

做法1:遍历0~num的数,计算它+它反转之后的数 是否为num,如果是,则返回true

class Solution {
public:
    int reverse(int n)    //反转整数
    {
        int sum = 0;
        while(n)
        {
            sum  = sum*10 + n%10;
            n/=10;
        }
        return sum;
    }
    bool sumOfNumberAndReverse(int num) {
        for(int i = 0;i<=num;i++) //暴力枚举
        {
            if(i + reverse(i) == num)
                return true;
        }
        return false;
    }
};

做法2:利用string,将数字转为字符串,直接反转

class Solution {
public:
    bool sumOfNumberAndReverse(int num) {
        for(int i = 0;i<=num;i++)
        {
            string s = to_string(i);//数字->字符串
            reverse(s.begin(),s.end());
            if(i + stoi(s) == num)//数 + 反转之后的数 == num
            {
                return true;
            }
        }
        return false;
    }
};

[2444. 统计定界子数组的数目]

leetcode.cn/problems/co…

image-20221018222256042

题目的要求是:子数组的范围要在mink~maxk当中,并且子数组当中存在至少一个mink,maxk

class Solution {
public:
//题目的要求是:子数组的范围要在mink~maxk当中,并且子数组当中存在至少一个mink,maxk
//所以把不在这个范围的数找出来,就可以把数据分为若干段,然后看每一段
long long countSubarrays(vector<int>& nums, int mink, int maxk) {
    long long res = 0; 
    int smin =0,smax =0;//记录当前子区间里面有多少个mink和maxk
​
    //j的含义:最靠近i的位置,使得[i,j]的区间中至少有一个mink,一个maxk
    //last的含义:表示上一次没有超过mink~maxk范围的数在哪里
    for( int i = 0,j = 0,last = 0;i<nums.size();i++)
    {
        if(nums[i] < mink || nums[i] > maxk) //当前数不在范围内
        {
            j = last = i+1;//下一个数才可能是符合范围的
            smin = smax = 0;//注意要清空!!!
            continue;
        }
        //当前位置是合法的
        //注意这里不能写else,因为mink可能和maxk是一样的
        if(nums[i] == mink) smin++;
        if(nums[i] == maxk) smax++;
        //j不断靠近i,直到走到当前[j,i]范围内没有至少一个mink或者maxk 就不符合条件 
        while(j<=i)
        {
            //看看跳过当前位置的数是否还符合规则
            if(nums[j] == mink) smin--;
            if(nums[j] == maxk) smax--;
            if(!smin || !smax) //不符合规则了!!
            {
                //smin或者smax没有了,说明j不能往后走了
                //恢复smin和smax的数量,是为了下面累加子数组个数
                if(nums[j] == mink) smin++;
                if(nums[j] == maxk) smax++;
                break;
            }
            j++;
        }
        if(smax && smin)
        {
            //j是符合要求的尾,last是符合要求的头位置 
            res += j-last+1; 
        }
    }
    return res;
}
};