美观的花束
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 144 ms, 内存: 26.9 MB
/*
* 思路:使用Java Stream来实现这个算法需要一些变通的方法,因为Stream并不直接支持滑动窗口操作。
* 我们可以先将数据进行处理,然后再使用Stream来进行结果的计算。
*/
import java.util.HashMap;
import java.util.stream.IntStream;
public class BeautifulBouquetStream {
public int countBeautifulBouquets(int[] flowers, int cnt) {
final int MOD = 1000000007;
int n = flowers.length;
HashMap<Integer, Integer> countMap = new HashMap<>();
int[] resultArray = new int[n];
int left = 0;
for (int right = 0; right < n; right++) {
countMap.put(flowers[right], countMap.getOrDefault(flowers[right], 0) + 1);
while (countMap.get(flowers[right]) > cnt) {
countMap.put(flowers[left], countMap.get(flowers[left]) - 1);
left++;
}
resultArray[right] = right - left + 1;
}
return IntStream.of(resultArray).reduce(0, (sum, value) -> (sum + value) % MOD);
}
public static void main(String[] args) {
BeautifulBouquetStream solution = new BeautifulBouquetStream();
int[] flowers1 = {1, 2, 3, 2};
int cnt1 = 1;
System.out.println(solution.countBeautifulBouquets(flowers1, cnt1)); // 输出:8
int[] flowers2 = {5, 3, 3, 3};
int cnt2 = 2;
System.out.println(solution.countBeautifulBouquets(flowers2, cnt2)); // 输出:8
}
}
解释
方法:
这个题解使用了滑动窗口(双指针)的方法来寻找所有满足条件的连续子数组(美观的花束)。维护两个指针i和l,其中i是当前考察的花的位置,而l是使得从l到i的子数组满足每种花的数量都不超过cnt的最小可能的起点。使用一个哈希表dic来记录窗口中每种花的数量。遍历flowers数组,对于每个花品种x,增加dic[x]的计数。如果dic[x]超过了cnt,说明当前窗口从l到i不再美观,因此需要将l右移直到dic[x]不超过cnt。每次右移l后,相应地减少dic[flowers[l]]的计数。每个有效的l到i的窗口都是一个美观的花束,i - l表示以i为结束位置的美观花束的数量。结果ans累加这些花束的数量,并且使用MOD来防止溢出。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在使用双指针法时,如何确定初始的左指针`l`的位置,为什么从`-1`开始而不是从`0`开始?
▷🦆
请解释为什么每次当`dic[x] > cnt`时,只移动左指针`l`一次就足够了,这是否确保了所有可能的美观花束都被考虑?
▷🦆
哈希表`dic`中记录了每种花的数量,但是如何处理在最后的输出结果中可能存在的重复计数问题?
▷