开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情
[2441. 与对应负数同时存在的最大正整数]
做法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. 反转之后不同整数的数目]
做法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. 反转之后的数字和]
某个数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. 统计定界子数组的数目]
题目的要求是:子数组的范围要在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;
}
};