开启掘金成长之旅!这是我参与「掘金日新计划 · 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.length1 <= n <= 1001 <= 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;
}
}