开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情
刷题的日常-2022年12月12号
一天一题,保持脑子清爽
所有子字符串美丽值之和
来自leetcode的 1781 题,题意如下:
一个字符串的 美丽值 定义为:出现频率最高字符与出现频率最低字符的出现次数之差。
比方说,"abaacc" 的美丽值为 3 - 1 = 2 。 给你一个字符串 s ,请你返回它所有子字符串的 美丽值 之和。
示例1:
输入:s = "aabcb"
输出:5
解释:美丽值不为零的字符串包括 ["aab","aabc","aabcb","abcb","bcb"] ,每一个字符串的美丽值都为 1 。
理解题意
通过题意,我们可以将信息整理如下:
- 题目给出一个字符串,要求我们返回字符串的 子串 的美丽值之和
- 美丽值是指字符串中字符出现的最大 最小数量之差
做题思路
题目要求我们返回的是 子字符串 的美丽值的和,所以我们需要枚举所有的子字符串,统计每个子串的美丽值,然后返回统计值。
需要枚举所有的子串,这步省略不了,所以时间复杂度至少为O(n ^ 2),所以就只能通过其它方式进行加速。我们可以用map的方式保存出现的字符,然后在扫描的过程中进行更新,更新完成之后就可以统计最大最小值,加到结果当中。步骤如下:
- 开辟一个数组用于保存字符数量
- 统计字符出现的数量
- 遍历字符串
- 将出现的字符数组进行拷贝
- 索引从后往前扫描,出去的字符需要减一
- 统计最大最小值加到结果当中
- 最后返回结果
- 当前出现的字符减一
- 返回最终结果
代码实现
代码实现如下:
public class Solution {
int[] map = new int[26];
public int beautySum(String s) {
int res = 0;
for (int i = 0; i < s.length(); i++) {
map[s.charAt(i) - 'a']++;
}
for (int i = 0; i < s.length(); i++) {
res += cnt(i, s);
map[s.charAt(i) - 'a']--;
}
return res;
}
public int cnt(int idx, String s) {
int res = 0, tmp, c;
int min, max;
int[] minMap = Arrays.copyOf(map, map.length);
tmp = s.length() - 1;
while (tmp > idx) {
c = s.charAt(tmp--) - 'a';
min = max = minMap[c];
for (int num : minMap) {
if (num != 0) {
min = Math.min(min, num);
max = Math.max(max, num);
}
}
minMap[c]--;
res += max - min;
}
return res;
}
}