leetcode
leetcode 1551 ~ 1600
所有子字符串美丽值之和

所有子字符串美丽值之和

难度:

标签:

题目描述

代码结果

运行时间: 1043 ms, 内存: 16.1 MB


/*
 * The beauty value of a string is defined as the difference between the
 * frequency of the most common character and the least common character.
 * For example, the beauty value of 'abaacc' is 3 - 1 = 2.
 * The task is to find the sum of the beauty values of all substrings of a given string.
 */

import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.util.Arrays;

public class SolutionStream {
    public int beautySum(String s) {
        return IntStream.range(0, s.length())
                .flatMap(i -> IntStream.range(i + 1, s.length() + 1)
                        .map(j -> s.substring(i, j))
                        .mapToInt(substr -> {
                            int[] freq = new int[26];
                            substr.chars().forEach(ch -> freq[ch - 'a']++);
                            int maxFreq = Arrays.stream(freq).max().getAsInt();
                            int minFreq = Arrays.stream(freq)
                                    .filter(f -> f > 0)
                                    .min().getAsInt();
                            return maxFreq - minFreq;
                        }))
                .sum();
    }
}

解释

方法:

该题解使用了一个嵌套循环的方法,外层循环遍历字符串s的所有可能的起始位置i,内层循环遍历从位置i开始的所有可能的结束位置j。对于每个子字符串s[i:j+1],使用一个哈希表h来记录每个字符的出现次数。同时,记录并更新当前子字符串中出现最频繁的字符的出现次数maxVal和出现最少的字符的出现次数minVal。每次内循环计算出一个新的子字符串时,都会更新哈希表,并重新计算maxVal和minVal,然后计算当前子字符串的美丽值(maxVal - minVal),并将其累加到总计数cnt中。最终返回总计数cnt作为所有子字符串的美丽值之和。

时间复杂度:

O(n^2 * k)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在每次内循环的结束时重新计算最低频率minVal,而不是在字符频率更新后立即进行?这样做有什么优缺点?
在每次内循环结束时重新计算最低频率minVal而不是在每次更新后立即进行,这样做主要是为了效率考虑。如果每增加一个字符就重新计算最低频率,那么每次更新字符频率后都需要遍历整个哈希表来寻找最小值,这会增加算法的时间复杂度。通过在每次内循环结束时重新计算,可以减少频繁的最小值搜索操作,从而提高效率。然而,这种方式仍然会导致在每次内循环结束时进行一次全哈希表的遍历,这在字符种类多的情况下依然是一个较大的计算负担。
🦆
在该算法中,哈希表h的更新策略是什么?它是如何处理字符的初始化和频率更新的?
在该算法中,哈希表h用于记录每个字符的出现频率。对于每个新出现的字符,如果字符不在哈希表中,算法会将其初始化为0并立即将其频率设置为1。如果字符已存在于哈希表中,则直接增加其计数。这种策略确保了每个字符的频率都能被准确记录与更新,便于算法在任何时刻都能获取到任何字符的当前频率。
🦆
算法中提到用maxVal和minVal来记录最大和最小频率,但在初始设置时这两个变量的值如何确定?
在算法的每次外循环开始时,maxVal和minVal都被初始化。maxVal初始化为0,因为在开始探索新的子字符串时,任何字符的出现频率都不会超过0。minVal的初始值也设为0,这在逻辑上可能看起来有些不符合实际情况,因为最小频率应当是至少1或更高。然而,在实际计算过程中,minVal会在遇到第一个字符后立即更新,因此初始值在实际使用中会被快速覆盖。
🦆
这种算法有效率问题吗?考虑到每次添加一个新字符就重新计算最小值,是否有更高效的方式来维护这个最低频率?
该算法在效率上确实存在问题,尤其是在处理大字符串和字符种类多的情况下。每次添加一个新字符时重新计算最小频率需要遍历整个哈希表,这使得算法的时间复杂度较高。一种更高效的方式是使用优先队列(或其他数据结构,如有序列表)来维护字符频率的排序。这样,每次字符频率更新时,可以更快地调整排序并直接访问最小和最大频率值。这虽然增加了额外的数据结构管理开销,但可以显著减少每次查找最小和最大频率的时间,从而提高总体效率。

相关问题