Leetcode 659 分割数组为连续子序列 (贪心)
题目描述:
输入一个按升序排序的整数数组(可能包含重复数字),你需要将它们分割成几个子序列,其中每个子序列至少包含三个连续整数。要求判断你能够完成上述要求的划分。
题解:
我们需要两个map,一个用来记录$key$出现的次数,记为mp;一个用来记录以$key$为结尾的合法序列的个数,记为$tail$。为了尽可能的使划分成立,我们期望新加入的数字尽可能多的加入到已经合法的序列中,因为只有重新建立一个新的序列才会导致不符合情况的划分出现。那么我们对于顺序遍历的数有如下操作
1)通过$tail$尽可能多的把数加入已经合法的序列中。
2)新建一个合法序列,这里只新建长度为3的初始序列,如果无法新建则return false
AC代码:
class Solution { public: // 贪心的一个处理方式 bool isPossible(vector<int>& nums) { map<int,int> mp; unordered_map<int,int> tail; // int len = nums.size(); int ans = 0; for(auto & num:nums) mp[num]++; for(auto& [key,value]:mp) { if(tail.find(key-1) != tail.end()) { int tmp = min(value,tail[key-1]); tail[key-1] -= tmp; tail[key] += tmp; value -= tmp; } // 如果每法通过之前的序列处理 新建一个 if(value > 0) { if(mp.find(key+1) == mp.end() || mp[key+1] == 0) return false; if(mp.find(key+2) == mp.end() || mp[key+2] == 0) return false; int tmp = min(mp[key+1],mp[key+2]); if(tmp < value) return false; value = 0; mp[key+1] -= tmp; mp[key+2] -= tmp; tail[key+2] += tmp; // tmp = min(tmp,value); } } return true; } };