力扣 - 第302场周赛(补题)

第一题

数组能形成多少数对

解题思路:

使用unordered_map<int,int>把整数和该整数在数组中出现的次数关联起来

class Solution 
{
public:
    vector<int> numberOfPairs(vector<int>& nums) 
    {
        unordered_map<int,int> m;
        //<key,value>:key表示整数,value表示该整数在数组中出现的次数

        for(auto n:nums)//遍历nums,往m中存入数据
          m[n]++;

        int ans0=0,ans1=0;

        for(auto [i1,i2]:m)//遍历m,得ans0
          ans0+=i2/2;

        ans1=nums.size()-ans0*2;

        return vector<int>{ans0,ans1};
    }
};

第二题

数位和相等数对的最大和

解题思路:

写一个GetSum()函数用于求数位和

使用map<int,vector<int> >把数位和与对应数位和的正整数的下标值关联起来

技巧性步骤是提前把数组排序

class Solution 
{
public:
    int GetSum(int num)//求数位和函数
    {
        int sum=0;

        while(num>0)
          {
              sum+=num%10;
              num/=10;
          }

        return sum;
    }
   
    int maximumSum(vector<int>& nums) 
    {
        map<int,vector<int> > M;
        //key代表数位和;value代表对应数位和的正整数的下标值,使用vector<int>存储

        sort(nums.begin(),nums.end());
        //提前把数组排序,下标值越大对应的正整数越大

        for(int i=0;i<nums.size();i++)
          M[GetSum(nums[i])].push_back(i);
        //越后被存入的下标值越大

        int ma_x=-1;

        for(int i=0;i<=81;i++)//由题设可知数位和最小为0,最大为81
          if(M[i].size()>=2)
            {
                int temp=nums[ M[i][M[i].size()-1] ]  +  nums[ M[i][M[i].size()-2] ];
//为了使得和尽可能大,所以选择最后两个下标(该数位和条件下的最大的两个下标)对应的正整数相加

                if(temp>ma_x)  ma_x=temp;
            }

        return ma_x;
    }
};

第三题

裁剪数字后查询第K小的数字

解题思路:

两个字符串比较大小的规则是从左往右逐个比较各自相同位置的字符,

字符相同则比较下一个位置字符,直到出现不同字符,字符大字符串就大,

若有一个字符串直到结束也没有出现不同字符,就认为较长的字符串较大。

根据该规则,相同长度的数字字符串大小比较的结果 和 数字大小比较的结果 相同

使用pair<string,int>把 裁剪后的字符串 和 字符串对应的下标值 关联起来

class Solution 
{
public:
  vector<int> smallestTrimmedNumbers(vector<string>& nums, vector<vector<int>>& queries) 
    {
        int l=nums[0].size();//l为字符串长度(每个字符串长度相等)

        vector<int> answer;//数组answer存储每次查询的结果

        for(int i=0;i<queries.size();i++)//处理每次查询
          {
              int k=queries[i][0];
              int trim=queries[i][1];

              vector< pair<string,int> > A(nums.size());
   //first存储裁剪后的字符串,second存储字符串对应的下标值,pair将两者关联起来

              for(int j=0;j<nums.size();j++)//对于每次查询都需要裁剪所有字符串
                {
                    string s=nums[j].substr(l-trim);//注意substr的使用
                    A[j]=make_pair(s,j);//注意make_pair的使用
                }

              sort(A.begin(),A.end());
              //需要熟悉字符串比大小的规则
              //sort函数默认对pair中的first从小到大排序
              //若first相等,则默认对pair中的second从小到大排序

              answer.push_back(A[k-1].second);
          }

        return answer;
    }
};

第四题

使数组可以被整除的最少删除次数

解题思路:

使用gcd()函数求numsDivide数组中所有正整数的最大公约数ma_x

那么,ma_x以及ma_x的因子就是所有的可以整除numsDivide数组中所有正整数的数

关键是找出ma_x以及ma_x的因子中的存在nums数组中的最小值,从而确定最少删除次数

class Solution 
{
public:
    int minOperations(vector<int>& nums, vector<int>& numsDivide) 
    {
        int ma_x=0;
        for(int i=0;i<numsDivide.size();i++)
          ma_x=gcd(ma_x,numsDivide[i]);
        //经过此轮for循环后,ma_x即为numsDivide数组中所有正整数的最大公约数

        sort(nums.begin(),nums.end());
        //为了删除次数尽可能少,应当选择尽可能小的数作为除数,所以提前排序nums数组

        int ans=-1;
        for(int i=0;i<nums.size();i++)
          if(ma_x % nums[i] == 0)//nums[i]就是符合题目要求的除数
            {
                ans=i;//比nums[i]小的数应当全部被删除
                break;
            }

        return ans;
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值