LeetCode 659
给你一个按升序排序的整数数组 num(可能包含重复数字),请你将它们分割成一个或多个子序列,其中每个子序列都由连续整数组成且长度至少为 3 。
如果可以完成上述分割,则返回 true ;否则,返回 false 。
示例 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, 10000]
分析:此题可以采用贪心算法和哈希表来解答。
例如[1,2,3,3,4,5],判断1,因为没有以0结尾的连续子序列,所以向后两个元素2,3形成子序列[1,2,3]。接下来判断3,没有以2结尾的子序列,所以与后两个元素组成子序列。
例如[1,2,3,3,4,4,5,5]。判断1,形成[1,2,3]。
判断3,形成[3,4,5]。
判断4,有4-1结尾的子序列,则4加入该子序列,形成[1,2,3,4]。
判断5,有5-1结尾的子序列,则5加入该子序列,形成[1,2,3,4,5]。
最终形成两个连续子序列[1,2,3,4,5]和[3,4,5]。
代码如下:
class Solution {
public:
bool isPossible(vector<int>& nums) {
unordered_map<int,int> numsCntMap;//表示的是num剩余的个数
unordered_map<int,int> numsEndMap;//表示以num结尾的子序列个数
//统计个元素出现次数
for(auto num:nums){
numsCntMap[num]+=1;
}
for(auto num:nums)
{
if(numsCntMap[num]==0) continue;//该元素用完
numsCntMap[num]-=1;
//判断是否存在以num-1结尾的子序列
if(numsEndMap.count(num-1)&&numsEndMap[num-1]>0){
numsEndMap[num-1]-=1;
numsEndMap[num]+=1;
}
//判断该元素是否能与后面的两个元素形成连续子序列
else if(numsCntMap.count(num+1)&&numsCntMap[num+1]&&numsCntMap.count(num+2)&&numsCntMap[num+2])
{
numsCntMap[num+1]-=1;
numsCntMap[num+2]-=1;
numsEndMap[num+2]+=1;
}
else return false;
}
return true;
}
};