分割数组为连续子序列
难度:
标签:
题目描述
代码结果
运行时间: 75 ms, 内存: 16.8 MB
/*
* 题目思路:
* 1. 使用 Java Stream 对输入数组进行处理。
* 2. 统计每个数字的出现次数。
* 3. 使用 Stream API 的特性来处理子序列的添加和创建。
*/
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SplitArrayIntoSubsequencesStream {
public boolean isPossible(int[] nums) {
Map<Integer, Long> freq = IntStream.of(nums).boxed()
.collect(Collectors.groupingBy(n -> n, Collectors.counting()));
Map<Integer, Long> appendFreq = new HashMap<>();
for (int num : nums) {
if (freq.get(num) == 0) continue;
if (appendFreq.getOrDefault(num, 0L) > 0) {
appendFreq.put(num, appendFreq.get(num) - 1);
appendFreq.put(num + 1, appendFreq.getOrDefault(num + 1, 0L) + 1);
} else if (freq.getOrDefault(num + 1, 0L) > 0 && freq.getOrDefault(num + 2, 0L) > 0) {
freq.put(num + 1, freq.get(num + 1) - 1);
freq.put(num + 2, freq.get(num + 2) - 1);
appendFreq.put(num + 3, appendFreq.getOrDefault(num + 3, 0L) + 1);
} else {
return false;
}
freq.put(num, freq.get(num) - 1);
}
return true;
}
}
解释
方法:
这个题解使用贪心算法和哈希表来判断能否将数组分割成满足条件的子序列。主要思路如下:
1. 先用一个哈希表count统计每个数字出现的次数
2. 再用一个哈希表tail记录以每个数字结尾的子序列个数
3. 遍历数组,对于每个数字n:
- 如果n-1结尾的子序列个数大于0,则将n加入n-1结尾的子序列中
- 否则,如果n+1和n+2的计数都大于0,则将n, n+1, n+2作为新的子序列
- 如果上述两种情况都不满足,说明无法构成满足条件的分割,返回false
4. 遍历结束后,说明可以进行满足条件的分割,返回true
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在判断是否可以将数字n加入到以n-1结尾的子序列中时,不需要检查以n-1结尾的子序列长度是否至少为3?
▷🦆
在创建新子序列时,为什么选择的是n, n+1, n+2这三个连续数字,是否有其他数字组合可能以及为什么不使用这些组合?
▷🦆
如果在处理过程中,n+1或n+2的count为0,但后面的数字中有可用的n+1和n+2,这种情况下如何处理以保证最优的子序列分割?
▷🦆
算法中提到如果无法生成满足条件的子序列则返回false,能否具体说明哪些情况下会发生这种无法生成的情况?
▷