(nice!!!)LeetCode 1542. 找出最长的超赞子字符串 (前缀和、位运算、状态压缩)

1542. 找出最长的超赞子字符串

在这里插入图片描述
在这里插入图片描述

思路:本题求的是一个最长的区间lens,区间里的数字满足:最多只有一个数字的数量为奇数个,其余数量都是偶数个。
1、求区间的问题,自然想到用前缀和,在这里,我们发现对于区间中数字的数量,我们只需要记住它是奇数个还是偶数个,这里就可以采用状态压缩,用0表示偶数,1表示奇数。
2、字符串都是由数字组成,也就是0~9,一共10个数字,采用状态压缩的话,出现的元素数量最多为1<<10-1,1023个,可以采用。
3、可以记住每一段从[0,i]区间的状态后,就可以通过前缀和来求出满足要求的区间。
4、细节看注释

class Solution {
public:
    int longestAwesome(string s) {
        int n=s.size();
        unordered_map<int ,int> mp;
        mp.insert({0,-1});//先初始化,便于区间[0,i]数字数量都是偶数的计算。
        int res=0;
        int lens=0;
        for(int i=0;i<n;i++){
            int tmp=s[i]-'0';
            res^=(1<<tmp);//通过异或,来改变奇偶性
            if(mp.count(res)){//如果前面[0,i-1]区间有相同状态的出现,那么存在一段区间数字数量都为偶数个。
                lens=max(lens,i-mp[res]);
            }
            //下面就是计算,有一个位置的奇偶性不同的情况
            for(int j=0;j<10;j++){
                int tmp=res^(1<<j);//与1异或都会改变当前位置的状态
                if(mp.count(tmp)){//看看前面[0,i-1]区间是否有:只不同一个位置的状态出现
                    lens=max(lens,i-mp[tmp]);
                }
            }
            //如果res在前面没有出现过,那就可以插入到哈希表中,不然就不能插入
            if(!mp.count(res))mp[res]=i;
        }
        return lens;
    }
};
  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值