6分钟
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 只包含小写英文字母。
思路
通过双指针i,j进行双层循环,能够获得字符串s所有的子字符串。
在每一次第二层循环之前,初始化一个长度为26的数组frequency,记录s[i]-s[j]组成的字符串中各字符出现的频率。
同时维护一个maxNum用于记录当前s[i]-s[j]组成的字符串中最高的字符出现频率。
在每一次子字符串获得后,获取s[i]-s[j]组成的字符串中最低的字符出现频率minNum。将maxNum和minNum的差值累加,最后得到result。
思路递推
以实例一中s=“aabcb"为例:
- 初始i = 0,j = 0。
- 初始化frequency数组,同时当前子字符串为"a”。
- s[j] = ‘a’,frequency[s[j] - ‘a’] = frequency[0] = 1,maxNum = 1(a),minNum = 1(a),差值为0,result += 0,此时result = 0。
- i = 0,j = 1。
- 当前子字符串为"aa"。
- s[j] = ‘a’,frequency[s[j] - ‘a’] = frequency[0] = 2,maxNum = 2(a),minNum = 2(a),差值为0,result += 0,此时result = 0。
- i = 0,j = 2。
- 当前子字符串为"aab"。
- s[j] = ‘b’,frequency[s[j] - ‘a’] = frequency[1] = 1,maxNum = 2(a),minNum = 1(b),差值为1,result += 1,此时result = 1。
- i = 0,j = 3。
- 当前子字符串为"aabc"。
- s[j] = ‘c’,frequency[s[j] - ‘a’] = frequency[2] = 1,maxNum = 2(a),minNum = 1(b/c),差值为1,result += 1,此时result = 2.
- i = 0,j = 4。
- 当前子字符串为"aabcb"。
- s[j] = ‘b’,frequency[s[j] - ‘a’] = frequency[1] = 2,maxNum = 2(a/b),minNum = 1(c),差值为1,result += 1,此时result = 3.
- i = 1,j = 1。
- 初始化frequency数组,同时当前子字符串为"a"。
- s[j] = ‘a’,frequency[s[j] - ‘a’] = frequency[0] = 1,maxNum = 1(a),minNum = 1(a),差值为0,result += 0,此时result = 3。
- i = 1,j = 2。
- 当前子字符串为"ab"。
- s[j] = ‘b’,frequency[s[j] - ‘a’] = frequency[1] = 1,maxNum = 1(a),minNum = 1(a/b),差值为0,result += 0,此时result = 3。
- i = 1,j = 3。
- 当前子字符串为"abc"。
- s[j] = ‘c’,frequency[s[j] - ‘a’] = frequency[2] = 1,maxNum = 1(a/b/c),minNum = 1(a/b/c),差值为0,result += 0,此时result = 3。
- i = 1,j = 4。
- 当前子字符串为"abcb"。
- s[j] = ‘b’,frequency[s[j] - ‘a’] = frequency[1] = 2,maxNum = 2(b),minNum = 1(a/c),差值为1,result += 1,此时result = 4。
- i = 2,j = 2。
- 初始化frequency数组,同时当前子字符串为"b"。
- s[j] = ‘b’,frequency[s[j] - ‘a’] = frequency[1] = 1,maxNum = 1(b),minNum = 1(b),差值为0,result += 0,此时result = 4。
- i = 2,j = 3。
- 当前子字符串为"bc"。
- s[j] = ‘c’,frequency[s[j] - ‘a’] = frequency[2] = 1,maxNum = 1(b/c),minNum = 1(b/c),差值为0,result += 0,此时result = 4。
- i = 2,j = 4。
- 当前子字符串为"bcb"。
- s[j] = ‘b’,frequency[s[j] - ‘a’] = frequency[1] = 2,maxNum = 2(b),minNum = 1(c),差值为0,result += 1,此时result = 5。
- i = 3,j = 3。
- 初始化frequency数组,同时当前子字符串为"c"。
- s[j] = ‘c’,frequency[s[j] - ‘a’] = frequency[2] = 1,maxNum = 1(c),minNum = 1(c),差值为0,result += 1,此时result = 5。
- i = 3,j = 4。
- 当前子字符串为"cb"。
- s[j] = ‘b’,frequency[s[j] - ‘a’] = frequency[1] = 1,maxNum = 1(b/c),minNum = 1(b/c),差值为0,result += 1,此时result = 5。
- i = 4,j = 4。
- 初始化frequency数组,同时当前子字符串为"b"。
- s[j] = ‘b’,frequency[s[j] - ‘a’] = frequency[1] = 1,maxNum = 1(b),minNum = 1(b),差值为0,result += 1,此时result = 5。
- 遍历结束,result最终为5。
代码实现
public static int beautySum(String s) {
int result = 0,length = s.length();
for (int i = 0; i < length; i++) {
// 记录s[i]-s[j]组成的字符串中各字符出现的频率
int[] frequency = new int[26];
// 记录s[i]-s[j]组成的字符串中字符出现最多的频率
int maxNum = 0;
for (int j = i; j < length; j++) {
char c = s.charAt(j);
// 更新频率
frequency[c - 'a']++;
// 遍历过程中直接选出当前最大的频率
maxNum = Math.max(maxNum,frequency[c - 'a']);
// 遍历频率数组,找出最小的频率
int minNum = length;
for (int k : frequency) {
if (k > 0){
minNum = Math.min(minNum,k);
}
}
// 差值累加
result += maxNum - minNum;
}
}
return result;
}
public static void test(){
System.out.println(beautySum("abaacc"));
System.out.println(beautySum("aabcb"));
System.out.println(beautySum("aabcbaa"));
}