Leetcode---361周赛

题目列表

2843. 统计对称整数的数目

2844. 生成特殊数字的最少操作

2845. 统计趣味子数组的数目

2846. 边权重均等查询

一、统计对称整数的数目

 这题看一眼数据范围,直接就可以开始暴力求解了,按照题目要求模拟就行,代码如下

class Solution {
public:
    int countSymmetricIntegers(int low, int high) {
        int ans=0;
        for(int i=low;i<=high;i++){
            string s=to_string(i);
            if(s.size()%2)continue;
            int m=s.size()/2;
            int diff=0;
            for(int j=0;j<m;j++)
                diff+=(s[j]-s[j+m]);
            if(diff==0)ans++;
        }
        return ans;
    }
};

二、生成特殊数字的最小操作数

这题其实也不难,只要知道25的倍数的特点就行,即末尾两位为00,25 ,50,75的数字,题目要求最小操作数,就是在这四种情况中找到操作数最小的,当然还要注意0也能被25的整除,所以当不满足前面四种情况时, 还要考虑数字中是否包含0,如果有返回n-1,如果没有返回n。

代码如下

class Solution {
public:
    int minimumOperations(string num) {
        int n=num.size();
        function<int(string)>f=[&](string s)->int{
            size_t pos=num.rfind(s[1]);
            if(pos==-1||pos==0)return n;
            pos=num.rfind(s[0],pos-1);
            if(pos==-1)return n;
            return n-pos-2;
        };
        int ret1=min(min(f("00"),f("25")),min(f("75"),f("50")));
        int ret2=n-(num.find('0')!=-1);
        return min(ret1,ret2);
    }
};

三、统计趣味子数组的数目

求满足条件的子数组的数量,一般都是用前缀和+哈希表,这题前缀和是求满足nums[i]%modulo=k的子数组的数量,这里有一些求余运算的数学知识,如下

假设s[ ]为前缀和数组,i<j,且(s[j]-s[i])%m=k,

那么s[j]%m-s[i]%m=k,即s[i]%m=s[j]%m-k,这里有一个细节要注意,s[j]%m-s[i]%m可能小于0,这样就需要+m之后再%m,才能得到正确的取模值,即s[j]%m-s[i]%m+m=k,s[i]%m=s[j]%m-k+m

综上所诉:无论s[j]%m-s[i]%m结果是正是负,s[i]%m=(s[j]%m-k+m)%m

 所以,哈希表只用记录s%m之后的值的数量即可

 代码如下

class Solution {
public:
    long long countInterestingSubarrays(vector<int>& nums, int m, int k) {
        long long ans=0;
        int s=0;
        unordered_map<int,int>hash;
        hash[0]=1;//这里要注意!!!,代表没有元素时,余数为0的情况
        for(auto x:nums){
            s+=(x%m==k);
            s%=m;
            ans+=hash[(s-k+m)%m];
            hash[s%m]++;
        }
        return ans;
    }
};

四、边权重均等查询

 思路如下:

代码如下 

class Solution {
public:
    vector<int> minOperationsQueries(int n, vector<vector<int>>& edges, vector<vector<int>>& queries) {
        //创建矩阵--记录每个点所连接的点和权值
        vector<vector<pair<int,int>>>g(n);
        for(auto& e:edges){
            int x=e[0],y=e[1],w=e[2]-1;
            g[x].push_back({y,w});
            g[y].push_back({x,w});
        }

        int m=32-__builtin_clz(n);//得到前导0的个数
        int cnt[n][m][26];
        memset(cnt,0,sizeof(cnt));
        int pa[n][m];
        memset(pa,-1,sizeof(pa));
        vector<int>depth(n);//记录每个点的深度
        function<void(int,int)> dfs=[&](int x,int father){
            pa[x][0]=father;
            for(auto [y,w]: g[x]){
                if(y!=father){
                    cnt[y][0][w]=1;
                    depth[y]=depth[x]+1;
                    dfs(y,x);
                }
            }
        };
        dfs(0,-1);

        //倍增
        for(int i=1;i<m;i++){
            for(int j=0;j<n;j++){
                int p=pa[j][i-1];
                if(p!=-1){
                    pa[j][i]=pa[p][i-1];
                    for(int k=0;k<26;k++){
                        cnt[j][i][k]=cnt[j][i-1][k]+cnt[p][i-1][k];
                    }
                }
            }
        }

        vector<int> ans;
        for(auto&e:queries){
            int a=e[0],b=e[1];
            int len=depth[a]+depth[b];
            if(depth[a]>depth[b])
                swap(a,b);
            int cw[26]{};

            //让x和y在同一高度
            for(int k=depth[b]-depth[a];k;k&=k-1){
                int idx=__builtin_ctz(k);
                int p=pa[b][idx];
                for(int j=0;j<26;j++)
                    cw[j]+=cnt[b][idx][j];
                b=p;
            }

            //同时向上跳
            if(a!=b){
                for(int i=m-1;i>=0;i--){
                    int A=pa[a][i],B=pa[b][i];
                    if(A!=B){
                        for(int k=0;k<26;k++){
                            cw[k]+=cnt[a][i][k]+cnt[b][i][k];
                        }
                        a=A,b=B;
                    }
                }
                //跳完之后,还在LAC下面一层
                for(int k=0;k<26;k++){
                    cw[k]+=cnt[a][0][k]+cnt[b][0][k];
                }
                a=pa[a][0];
            }
            int lca=a;
            len-=depth[lca]*2;
            ans.push_back(len-*max_element(cw,cw+26));
        }
        return ans;
    }
};

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值