统计好分割方案的数目
难度:
标签:
题目描述
You are given a 0-indexed array nums
consisting of positive integers.
A partition of an array into one or more contiguous subarrays is called good if no two subarrays contain the same number.
Return the total number of good partitions of nums
.
Since the answer may be large, return it modulo 109 + 7
.
Example 1:
Input: nums = [1,2,3,4] Output: 8 Explanation: The 8 possible good partitions are: ([1], [2], [3], [4]), ([1], [2], [3,4]), ([1], [2,3], [4]), ([1], [2,3,4]), ([1,2], [3], [4]), ([1,2], [3,4]), ([1,2,3], [4]), and ([1,2,3,4]).
Example 2:
Input: nums = [1,1,1,1] Output: 1 Explanation: The only possible good partition is: ([1,1,1,1]).
Example 3:
Input: nums = [1,2,1,3] Output: 2 Explanation: The 2 possible good partitions are: ([1,2,1], [3]) and ([1,2,1,3]).
Constraints:
1 <= nums.length <= 105
1 <= nums[i] <= 109
代码结果
运行时间: 131 ms, 内存: 35.4 MB
// Java solution using Streams
// Problem description: Given an array of positive integers, find the number of good split schemes. A good split scheme is defined as splitting the array into one or more continuous subarrays where no two subarrays contain the same number.
// Approach: We use Java Streams to handle data manipulation. We maintain sets for the left and right partitions and use sets to track unique elements. The process involves adjusting sets as we iterate through the array.
import java.util.*;
import java.util.stream.Collectors;
public class GoodSplitSchemesStream {
public static int countGoodSplits(int[] nums) {
final int MOD = 1000000007;
Set<Integer> leftSet = new HashSet<>();
Set<Integer> rightSet = Arrays.stream(nums).boxed().collect(Collectors.toSet());
int goodSplits = 0;
for (int num : nums) {
leftSet.add(num);
rightSet.remove(num);
if (leftSet.size() == rightSet.size()) {
goodSplits = (goodSplits + 1) % MOD;
}
}
return goodSplits;
}
}
解释
方法:
题解的核心思路是识别数组中可以形成好分割的点。首先,创建一个字典来记录每个元素最后一次出现的位置。然后遍历数组,对每个元素更新其最后一次出现的位置,同时维护一个变量max_r来记录当前遍历到的位置所能达到的最远右边界。当遍历的索引与max_r相等时,意味着到目前为止的所有元素可以构成一个好分割的子数组。每识别出一个这样的点,我们将计数器加一。最终,好分割的方案数为2的(m-1)次方,其中m是识别出的好分割点的数量,因为每一个好分割点都可以选择分割或不分割。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
题解中提到创建一个字典来记录每个元素最后一次出现的位置,为什么只记录最后一次出现的位置,而不是所有出现的位置?
▷🦆
在更新最大右边界`max_r`时,为什么选择`max(max_r, dic[x])`?这种方法是否确保了所有元素只属于一个子数组内?
▷🦆
题解中提到,当遍历的索引与最大右边界`max_r`相等时,可以形成一个好分割的子数组,这个逻辑是如何确保子数组中不包含重复元素的?
▷🦆
题解说最终的好分割方案数为`2的(m-1)次方`,能否解释为什么是`(m-1)次方`而不是`m次方`?
▷