力扣:第313场周赛

1,886 阅读1分钟

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

力扣——第313场周赛

2427. 公因子的数目

问题解析

先对a分解因数,并且用哈希表记录下来。

再对b分解因数,如果已经在哈希表出现过了,计数器++。要注意的是,b可能是某个整数的平方数,此时它的平方根只看做一个因子,不要重复计算。

AC代码

class Solution {
public:
    int commonFactors(int a, int b) {
        unordered_map<int,int>mymap;
        int cnt=0;
        for(int i=1;i<=a/i;i++)
        {
            if(a%i==0)
            {
                mymap[i]++;
                mymap[a/i]++;
            }
        }
        for(int i=1;i<=b/i;i++)
        {
            if(b%i==0)
            {
                if(mymap.count(i))cnt++;
                if(b/i!=i&&mymap.count(b/i))cnt++;
            }
        }
        return cnt;
    }
};

2428. 沙漏的最大总和

问题解析

因为数据很小(但其实大了也没关系)我们直接暴力枚举每个沙漏左上角的点,然后算这个沙漏的分数。

AC代码

class Solution {
public:
    int check(int x,int y,vector<vector<int>>& grid)
    {
        int sum=grid[x+1][y+1];
        for(int i=y;i<y+3;i++)
        {
            sum+=grid[x][i];
            sum+=grid[x+2][i];
        }
​
        return sum;
    }
    int maxSum(vector<vector<int>>& grid) {
        int res=0;
        int n=grid.size(),m=grid[0].size();
        for(int i=0;i<=n-3;i++)
        {
            for(int j=0;j<=m-3;j++)
            {
                res=max(res,check(i,j,grid));
            }
        }
        return res;
    }
};

2429. 最小 XOR

问题解析

先计算出num2的二进制中1的数目a,再计算出num1的二进制中1的数目b,比较他们的大小(为了方便我这里用一个变量cnt来计算):

  1. 如果a==b(对应cnt==0) 那么x直接等于num1时就可以,此时x^num1的值为0.
  2. 如果a>b(对应cnt>0) ,我们要在x等于num1的基础上多加几个1,根据贪心的思想,这几个1的位置越小,x^num1的结果就越小。所以我们要找cnt个num1二进制下最小的0,把他们变成1,这就是我们要的x。
  3. 如果a<b(对应cnt<0) ,那如果想获得最小的x^num1,我们就把num1二进制下,cnt个最大位置上的1变成0,这就是我们要的x.

AC代码

class Solution {
public:
    int minimizeXor(int num1, int num2) {
        int cnt=0;
        for(int i=0;i<31;i++)
        {
            if((num2>>i)&1)cnt++;
            if((num1>>i)&1)cnt--;
        }
        if(cnt==0)return num1;
        else if(cnt>0)
        {
            int res=num1;
            for(int i=0;i<31;i++)
            {
                if(cnt==0)break;
                if(!((num1>>i)&1))
                {
                    res+=(1<<i);
                    cnt--;
                }
            }
            return res;
        }
        int res = num1;
        for (int i = 0; i < 31; i++)
        {
            if (cnt == 0)break;
            if (((num1 >> i) & 1))
            {
                res -= (1 << i);
                cnt++;
            }
        }
        return res;
    }
};

2430. 对字母串可执行的最大删除数

问题解析

设立状态数组f,f[i]表示,i之后的字符串全被删除最多需要f[i]次。答案为f[0]。

从后往前枚举字符串起点i,并枚举字符串长度j,如果字符串i+1~ji+j+1~i+2*j相等,则有f[i]=f[i+j]+1。

枚举字符串总复杂度为n^2。如果加上判断字符串相等,则是n^3,我们要想办法优化。

可以用字符串哈希的方法来判断两个字符串是否相等,预处理O(n),每次对比的时间复杂度为O(1)。这样这题的总复杂度就可以达到O(n^2)。

AC代码

class Solution {
public:
    typedef unsigned long long ull;
    int n,m,p=99971,base=13331;
    int f[4050];
    ull get_hash(vector<ull>&v,int l,int r,vector<ull>&bpow)
    {
        ull t=v[l-1]*bpow[r-l+1];
        return (v[r]-t);
    }
    
    int deleteString(string s) {
        int n=s.size();
        vector<ull>v(n+1),bpow(n+1,1);
        ull res=0;
        for(int i=1;i<=n;i++)
        {
            res=(res*base+s[i-1]);
            v[i]=res;
            bpow[i]=bpow[i-1]*base;
        }
        for(int i=n-1;i>=0;i--)
        {
            f[i]=1;
            for(int j=1;i+2*j<=n;j++)
            {
                int a=get_hash(v,i+1,i+j,bpow),b=get_hash(v,i+j+1,i+2*j,bpow);
                if(a==b)
                {
                    f[i]=max(f[i],f[i+j]+1);
                }
            }
        }
        return f[0];
    }
};