[LeetCode 1781]所有子字符串美丽值之和

题目描述

题目链接:所有子字符串美丽值之和

一个字符串的 美丽值 定义为:出现频率最高字符与出现频率最低字符的出现次数之差。

比方说,“abaacc” 的美丽值为 3 - 1 = 2 。
给你一个字符串 s ,请你返回它所有子字符串的 美丽值 之和。

示例1

输入:s = “aabcb”
输出:5
解释:美丽值不为零的字符串包括 [“aab”,“aabc”,“aabcb”,“abcb”,“bcb”] ,每一个字符串的美丽值都为 1 。

示例2

输入:s = “aabcbaa”
输出:17

提示:

  • 1 <= s.length <= 500
  • s 只包含小写英文字母。

思路分析

前缀和
要想快速得到某个区间内某个字母出现的次数,使用前缀和可以在O(1)的时间内得到结果

由于有26个英文字母,所以我们开26个一维数组,每个一维数组存放对应字母的前缀和

以aabcb举例,首先是a,所以cnt[0][1]++,其余的cnt不变
在这里插入图片描述

同样s[2] = a,所以,cnt[0][2]++,其余不变
在这里插入图片描述

以此类推,最后得到的结果是
在这里插入图片描述

例如要求s[2~4] = abc
那么其中含有a的个数为cnt[0][4] - cnt[0][1] = 1
那么其中含有b的个数为cnt[1][4] - cnt[1][1] = 1
那么其中含有c的个数为cnt[2][4] - cnt[2][1] = 1

所以可以在常数时间内求出每一段子字符串中每个字母的个数

代码

int cnt[26][510];

class Solution {
public:
    int beautySum(string s) {
    	//一定要初始化,即使cnt放在class以外,其内部的值也是未经过初始化的
        memset(cnt, 0, sizeof cnt);
        //要计算前缀和,所以在s前加一个空格,不用进行下标转换
        s = ' ' + s;
		//计算前缀和数组
        for(int i = 1; i < s.size(); i++) {
            for(int j = 0; j < 26; j++) {
                cnt[j][i] += cnt[j][i - 1];
            }
            cnt[s[i] - 'a'][i]++;
        }

        int res = 0;
        //长度从3开始计算,长度为1和2都没有意义(不信你举个例子)
        for(int k = 3; k < s.size(); k++) {
            for(int i = 1; i + k - 1 < s.size(); i++) {
                int maxn = -1, minn = 1e9;
                for(int j = 0; j < 26; j++) {
                    int t = cnt[j][i + k - 1] - cnt[j][i - 1];
                    //如果这个区间内没有该字母,跳过!
                    if(!t) continue;
                    if(t > maxn) maxn = t;
                    if(t < minn) minn = t;
                }
                res += maxn - minn;
            }
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值