问题:
给定数组,和整数k
是否能将数组 刚好平均分配为,每k个一组连续递增子数组。
Example 1: Input: nums = [1,2,3,3,4,4,5,6], k = 4 Output: true Explanation: Array can be divided into [1,2,3,4] and [3,4,5,6]. Example 2: Input: nums = [3,2,1,2,3,4,3,4,5,9,10,11], k = 3 Output: true Explanation: Array can be divided into [1,2,3] , [2,3,4] , [3,4,5] and [9,10,11]. Example 3: Input: nums = [3,3,2,2,1,1], k = 3 Output: true Example 4: Input: nums = [1,2,3,4], k = 3 Output: false Explanation: Each array should be divided in subarrays of size 3. Constraints: 1 <= nums.length <= 10^5 1 <= nums[i] <= 10^9 1 <= k <= nums.length
解法:
解法一:
首先将原数组元素计数,到map【nummap】中
遍历 nummap,每k个为一组,
nummap[0],为小组第一个元素为准,以后的k-1个元素出现次数都-第一个元素出现的次数n(k-1个元素剩下的次数覆盖原值),
证明以第一个元素为首,首先能分成n个小组。
若以后的k-1个元素出现次数 < 第一个元素出现的次数n,那直接返回false。
然后继续遍历第二个元素nummap[1],为小组第一个元素。重复上述操作。
最终遍历完nummap所有元素,都没有返回false。那么证明分配完毕。
返回true。
代码参考:
1 class Solution { 2 public: 3 bool isPossibleDivide(vector<int>& nums, int k) { 4 if(nums.size()%k) return false; 5 map<int,int> nummap; 6 for(int n:nums){ 7 nummap[n]++; 8 } 9 for(auto nm:nummap){ 10 if(nm.second>0){ 11 for(int j=nm.first; j<nm.first+k; j++){ 12 if(nummap[j]<nm.second) return false; 13 nummap[j]-=nm.second; 14 } 15 } 16 } 17 return true; 18 } 19 };
解法二:
使用queue记录,当前开启的k个元素的小组个数。
这个queue最多保存时长为k,即size为k。
因为,假如当前遍历完第x个元素(记录完当前开启的小组数queue.push),在第x-k个元素时,所开启的小组,
到现在为止,已经连续保存了k个数值了,是时候结束生命周期。因此此时,需要关闭遍历x-k个元素时,所开启的小组。
opened记录当前开启的总小组个数,也即是当前元素的出现个数cout。
lastchecked记录当前元素val。
首先同解法一,
将原数组元素计数,到map【nummap】中
遍历 nummap,第一个元素val出现次数 cout
那么当前开启的小组数为cout
判断:如果当前元素val和上一个元素lastchecked不连续:opened>0 && val>lastchecked+1
或者,当前元素出现次数 < 当前开启的小组总数opened,那么直接返回 false。
若满足题意,未返回false。
那么将新追加开启的小组个数 cout-opened 存入queue中。queue.push
更新当前总开启组数opened和上一次检查元素对象lastchecked
加完当前元素后,判断queue的size是否到达k,
到达的时候,弹出最早开启中的小组。视为关闭。更新当前开启的小组总数opened-=queue.front。
当遍历完所有元素后,opened的个数应为0,才说明刚好分配完毕。
若不为0,那么返回false。
代码参考:
1 class Solution { 2 public: 3 bool isPossibleDivide(vector<int>& nums, int k) { 4 if(nums.size()%k) return false; 5 map<int,int> nummap; 6 for(int n:nums){ 7 nummap[n]++; 8 } 9 queue<int> start; 10 int opened=0, lastchecked=-1; 11 for(auto nm:nummap){ 12 int val=nm.first; 13 int cout=nm.second; 14 if(opened>0 && val>lastchecked+1 || opened>cout) return false; 15 start.push(cout-opened); 16 opened=cout; 17 lastchecked=val; 18 if(start.size()==k){ 19 opened-=start.front(); 20 start.pop(); 21 } 22 } 23 return opened==0; 24 } 25 };