[杨小白]_leetcode_力扣_12月12日每日一题_1781. 所有子字符串美丽值之和

79 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情

前言

小白算法比较菜,希望能激励我每日更新,从leetcode第一题开始,2022年目标2000分,现在1916!!

12月12日每日一题

1781. 所有子字符串美丽值之和

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

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

示例 1:

输入:s = "aabcb"

输出:5

解释:美丽值不为零的字符串包括 ["aab","aabc","aabcb","abcb","bcb"] ,每一个字符串的美丽值都为 1 。

示例 2:

输入: s = "aabcbaa"

输出: 17

提示:

  • n == cuboids.length
  • 1 <= n <= 100
  • 1 <= widthi, lengthi, heighti <= 100

代码

果然,最美的数据结构是数组,最好的算法是暴力。

用两个下标 i 和 j 表示子字符串的两端。用双层循环来遍历所有子字符串,第一层循环子字符串的起点 i,第二层循环固定 i,遍历子字符串的终点j。

遍历的时候需要维护dp数组,来记录i到j中间出现的字母分别出现过多少次。

这里引入min和max,可以减少从数组中寻找最小值的次数,优化时间复杂度。但是有一些细节需要注意,谨防踩坑。

复杂度分析

  • 时间复杂度:O(m * n^2),其中 m 是 26 ,字母的数字,n 是 s 的长度。

  • 空间复杂度:O(m),其中 m 是 26。

解法

class Solution {
    public int beautySum(String s) {
        int res = 0;
        char[] chars = s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            int[] dp = new int[26];
            int max = 0;
            int min = 0;
            for (int j = i; j < chars.length; j++) {
                char aChar = chars[j];
                int i1 = dp[aChar - 'a'];
                dp[aChar - 'a']++;
                if (i1 == min) {
                    min = findMid(dp);
                }
                if (i1 < min) {
                    min = i1 + 1;
                }
                if (i1 == max) {
                    max = i1 + 1;
                }
                res = res + max - min;
            }
        }
        return res;
    }

    private int findMid(int[] dp) {
        int res = 500;
        for (int i = 0; i < dp.length; i++) {
            if (dp[i]!= 0) {
                res = Math.min(dp[i],res);
            }
        }
        return res;
    }
}