Split Array into Consecutive Subsequences 分割数组为连续子序列

输入一个按升序排序的整数数组(可能包含重复数字),你需要将它们分割成几个子序列,其中每个子序列至少包含三个连续整数。返回你是否能做出这样的分割?

示例 1:

输入: [1,2,3,3,4,5]
输出: True
解释:
你可以分割出这样两个连续子序列 : 
1, 2, 3
3, 4, 5

示例 2:

输入: [1,2,3,3,4,4,5,5]
输出: True
解释:
你可以分割出这样两个连续子序列 : 
1, 2, 3, 4, 5
3, 4, 5

示例 3:

输入: [1,2,3,4,4,5]
输出: False

提示:

  1. 输入的数组长度范围为 [1, 10000]

思路:这道题是通过维护两个map来做的,第一个freq是对应数字出现的次数,第二个need是对应数字待拼接的次数(举例子如果数组是[1,2,3,3,4,4,5,5] ,那么当遍历到1时,发现其后两个数字2,3可以和1组成数列,那么4就可以拼接到[1,2,3]这个数列后面,所以need[4]++,那么当遍历到4时,发现他可以拼接到已有的数列中,这里大家有问题了,为什么4不能作为一个新的数列的开头呢?这个问题后面会说)。那么我们的做法就是先统计每个数字出现的次数。然后在第二次循环的时候,先判断当前数字次数是否为0,如果为0就跳过(为0证明当前数字已经被前面的数字承包了,比如[1,2,3,3],当遍历到1时,2,3的次数都被减1了,2的次数变成0,3的次数变成1,那么当遍历到2的时候就直接跳过,遍历到3的时候才不跳过急需处理),否则判断当前数字的need是否大于0,如果大于0就把当前数字的need减1,(当前数字+1)对应的数字的need+1(need表示当前的数字可以被拼接到已有数列后面的次数),如果上面两种情况都不满足(当前数字既没有被前面的数字承包(freq等于0),也不能拼接到任何一个数列后面),那么只能作为一个新数列的开头了,并且会越级的先承包后面两个数字并且把后面第三个数字的need可拼接次数+1。

参考代码:

class Solution {
public:
    bool isPossible(vector& nums) {
	unordered_map freq, need;
	for (auto num : nums) freq[num]++;
	for (auto num : nums) {
		if (!freq[num]) continue;
		else if (need[num] > 0) {
			need[num]--;
			need[num + 1]++;
		}
		else if (freq[num + 1]>0 && freq[num + 2]>0) {
			freq[num + 1]--;
			freq[num + 2]--;
			need[num + 3]++;
		}
		else return false;
        freq[num]--;
	}
	return true;        
    }
};

 

你可能感兴趣的:(算法)