659. Split Array into Consecutive Subsequences 堆、优先级队列、哈希表

来源:互联网 发布:win10安装连接网络出错 编辑:程序博客网 时间:2024/05/17 22:27

You are given an integer array sorted in ascending order (may contain duplicates), you need to split them into several subsequences, where each subsequences consist of at least 3 consecutive integers. Return whether you can make such a split.

Example 1:

Input: [1,2,3,3,4,5]Output: TrueExplanation:You can split them into two consecutive subsequences : 1, 2, 33, 4, 5

Example 2:

Input: [1,2,3,3,4,4,5,5]Output: TrueExplanation:You can split them into two consecutive subsequences : 1, 2, 3, 4, 53, 4, 5

Example 3:

Input: [1,2,3,4,4,5]Output: False

Note:

  1. The length of the input is in range of [1, 10000]
思路 1:使用两个哈希表,这里是贪心的思想:如果当前的数可以放在之前的序列之后,就放,若果不行,就形成一个新的序列。下面的代码的思路是:通过设置一个chance数组,提供这样的后续延续机会,因为数组是排过序的,遇到重复的数首先是构成新的数列。
class Solution {public:    bool isPossible(vector<int>& nums) {        //这个题就是模拟取数的过程        //在取数的时候,刚开始的时候取三个数,遇到新的数加在之前形成的数之后;遇到重复的数,重新行程一个三数组合。        //下面使用两个哈希表,一个统计所有数出现的次数,另外一个是取数的时候做统计。        //关键是另外一个哈希表的意义:表示当前数的潜在填补可能数,比如chance[i]==2,说明i这个数在之前有两个已经形成的序列后可以放进去。        //每当一个数用上了,就在freq中减掉,如果潜在位置数也用了一个,也减1        //在下面的代码中进行详细的说明                //问题的核心是:对于已经形成的序列,后面都有一个位置可以再添加一个数,我们成他为一个机会。就是说如果这个机会对应的数如果不能用于组成另外一个序列,他还可以有这个机会添加到已经构成的序列后面。因为是排过序的,如果没有重复的数,当前的序列会不断扩充。        //遇到了重复的数,当前的已知序列没有能提供这个机会添加到后面,那么这个数要行程一个长度为3的新序列,同时也增加一个尾添加机会        unordered_map<int,int> freq;//统计所有数的出现次数        unordered_map<int,int> chance;        for(int i=0;i<nums.size();i++)            freq[nums[i]]++;        for(auto i:nums)        {            if(freq[i]==0) continue;//当前数已经用完            if(chance[i]>0)//有序列可以有位置包养当前的数,就使用一个位置            {                chance[i]--;//这个位置少了一个机会                chance[i+1]++;//下一个位置多了一个容纳下一个数的位置            }            else if(freq[i+1]>0&&freq[i+2]>0)//现在没有序列可以容纳当前的元素,说明出现了重复的值,或者是中间断裂。因此需要形成一个新的序列            {                freq[i+1]--;                freq[i+2]--;                chance[i+3]++;            }            else return false;            freq[i]--;        }        return true;            }};
思路2:
这种思路类似。通过设置一个哈希表,键是当前序列的最后一个数,值是一个最小堆,意思是构成一个以这个数结尾的对应的所有序列,序列长度最小的那个排在堆顶。对于一个新的数,首先寻找他能不能在放到别的序列后面,而且是找长度小的那个放,放了之后,将这个堆顶弹出,在当前数结尾的堆中加入新的长度值。如果找不到现有序列去放这个数,就要开辟一个新的序列结尾。同时设置一个 变量。每当形成一个新的序列,need_more加1,当这个序列达到3时,need_more减一。
因为长度大于3序列已经满足要求了,长度小于3的序列需要首先满足。
如果最终need_more 不等于0,说明有的序列没有达到三个
class Solution {public:bool isPossible(vector<int>& nums){unordered_map<int, priority_queue<int, vector<int>, std::greater<int>>> backs;// Keep track of the number of sequences with size < 3int need_more = 0;for (int num : nums){if (! backs[num - 1].empty()){// There exists a sequence that ends in num-1// Append 'num' to this sequence// Remove the existing sequence// Add a new sequence ending in 'num' with size incremented by 1 int count = backs[num - 1].top();backs[num - 1].pop();backs[num].push(++count);if (count == 3)need_more--;}else{// There is no sequence that ends in num-1// Create a new sequence with size 1 that ends with 'num'backs[num].push(1);need_more++;}}return need_more == 0;}};



阅读全文
0 0