LeetCode---378周赛

题目列表

2980. 检查按位或是否存在尾随零

2981. 找出出现至少三次的最长特殊子字符串 I

2982. 找出出现至少三次的最长特殊子字符串 II

2983. 回文串重新排列查询

一、检查按位或是否存在尾随零

这题和位运算有关,不是很难,题目要求至少有两个数的或运算存在一个尾随零,那么我们只管检查每个数字的二进制的最低位是否为0即可,即判断数字的奇偶性(奇数的二进制最低位为1,偶数的二进制最低位为0)

代码如下

class Solution {
public:
    bool hasTrailingZeros(vector<int>& nums) {
        int cnt=0;
        for(auto&e:nums){
            if((e&1)==0){
                cnt++;
            }
        }
        return cnt>=2;
    }
};

 二、找出出现至少三次的最长特殊子字符串I&II

由于下一题和这一题一样,只是数据范围不同,我就一起讲了

这题其实是个分类讨论的题目,不是很难,但是要把细节想清楚,具体的分析如下:

首先弄清楚定义 --- 特殊子字符串是指由单一元素构成的字符串(要求连续),这其实就启发我们要将字符串拆分成一个个由相同字母组成的子字符串来分析问题,同时我们只关心子字符串的长度问题,所以我们可以提前处理得到由单一字母组成的子字符串长度数组

(用哈希表unordered_map<char,vector<int>>存放,具体看代码)

然后我们来分析单一字母组成的字符串长度数组该如何处理

(假设数组中的最大元素为L1,第二大元素为L2,第三大元素为L3,满足L1>=L2>=L3)

1、用数组中的一个元素(即一段字符串)来得到出现3次的特殊字符串,肯定选择最大长度的字符串,答案为L1 - 2   (这个公式是观察出来的可以举几个例子看看)

2、用数组中的两个元素(即两段字符串)来得到出现3次的特殊字符串,肯定选择最大长度和次大长度的字符串

        2.1、L1=L2,答案为L1 - 1

        2.2、L1>L2,答案为L2

        答案为min( L1 - 1,L2 )

3、用数组中的三个元素(即三段字符串)来得到出现3次的特殊字符串,肯定选择最大长度和次大长度和第三大长度的字符串,答案为L3

(如果L1=L2=L3,答案为L3,如果L1>L2=L3,答案为L3,如果L1>L2>L3,答案为L3)

综上所诉:答案为max(L1,min( L1 - 1,L2 ),L3)

【注意】上面所有的结论均是观察出来的

考虑到不是所有的数组大小都>=3,我们可以提前往数组中加入两个0,方便后面代码的书写

代码如下

class Solution {
public:
    int maximumLength(string s) {
        int n=s.size();
        unordered_map<char,vector<int>>mp;
        char x=s[0];
        int len=0;
        for(int i=0;i<n;i++){
            if(x==s[i]) len++;
            else{
                mp[x].push_back(len);
                len=1;
                x=s[i];
            }
        }
        mp[x].push_back(len);

        int ans=0;
        for(auto it=mp.begin();it!=mp.end();++it){
            auto& v=it->second;
            v.push_back(0);
            v.push_back(0);
            sort(v.begin(),v.end(),greater<int>());
            int L1=v[0],L2=v[1],L3=v[2];
            int res=max(L1-2,max(min(L1-1,L2),L3));
            ans=max(ans,res);
        }
        return ans?ans:-1;
    }
};

三、回文串重新排列查询

这题是大模拟,里面用到一些小技巧,单个来看它们不是很难,但要把它们组合在一起就不简单了

题目意思很明确,就是一个字符串,告诉你它的左右两边各有一段区间可以"修改",要你判断是否能将它变成回文串,返回所有查询的结果

技巧一:我们可以将字符串的左右两个部分拆分开来,然后将右边的字符串翻转一下,那么现在的问题就成了能否让两个字符串相等(由于题目给的字符串长度为偶数,不用担心中间元素如何处理的问题)

代码如下

class Solution {
public:
    vector<bool> canMakePalindromeQueries(string str, vector<vector<int>>& queries) {
        //技巧一
        int n=str.size()/2;
        string s=str.substr(0,n),t=str.substr(n);
        reverse(t.begin(),t.end());
        //预处理
        //技巧二
        vector<int>dif(n+1);
        for(int i=0;i<n;i++) 
            dif[i+1]=dif[i]+(s[i]!=t[i]);

        //技巧三
        vector<vector<int>>pre_s(26,vector<int>(n+1));
        auto pre_t=pre_s;
        for(int i=0;i<n;i++){
            for(int j=0;j<26;j++){
                pre_s[j][i+1]=pre_s[j][i];
                pre_t[j][i+1]=pre_t[j][i];   
            }
            int si=s[i]-'a',ti=t[i]-'a';
            pre_s[si][i+1]++;
            pre_t[ti][i+1]++;
        }

        auto substract=[&](int l,int r)->bool{
            for(int i=0;i<26;i++){
                if(pre_s[i][r+1]-pre_s[i][l]!=pre_t[i][r+1]-pre_t[i][l])
                    return false;
            }
            return true;
        };

        auto check=[&](int sl,int sr,int tl,int tr,vector<vector<int>>&pre_s,vector<vector<int>>&pre_t)->bool{
            if(dif[sl]||dif[n]-dif[max(tr,sr)+1])//[0,sl) [tr+1,n)区间内的字符严格相等---是三种情况的共同条件,这里把它放到最前面判断
                return false;
            if(sr<tl){
                return dif[tl]-dif[sr+1]==0&&substract(sl,sr)&&substract(tl,tr);
            }else{
                if(tr<=sr){
                    return substract(sl,sr);
                }else{
                    vector<int>tmp1(26),tmp2(26);
                    for(int i=0;i<26;i++){
                        tmp1[i]=pre_s[i][sr+1]-pre_s[i][sl];
                        tmp2[i]=pre_t[i][tr+1]-pre_t[i][tl];

                        tmp1[i]-=pre_t[i][tl]-pre_t[i][sl];
                        tmp2[i]-=pre_s[i][tr+1]-pre_s[i][sr+1];
                        if(tmp1[i]<0||tmp2[i]<0)//这里一定要判断
                            return false;
                    }
                    return tmp1==tmp2;
                }
            }
        };

        vector<bool>ans(queries.size());
        for(int i=0;i<queries.size();i++){
            int sl=queries[i][0],sr=queries[i][1];
            int tl=2*n-1-queries[i][3],tr=2*n-1-queries[i][2];//右边的区间需要修正一下
            ans[i] = sl<=tl?check(sl,sr,tl,tr,pre_s,pre_t):check(tl,tr,sl,sr,pre_t,pre_s);
        }
        return ans;
    }
};

  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值