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: True Explanation: You can split them into two consecutive subsequences : 1, 2, 3 3, 4, 5
Example 2:
Input: [1,2,3,3,4,4,5,5] Output: True Explanation: You can split them into two consecutive subsequences : 1, 2, 3, 4, 5 3, 4, 5
Example 3:
Input: [1,2,3,4,4,5] Output: False
Note:
- The length of the input is in range of [1, 10000]
題目分類應屬於 模擬。
題目大意,將一升序的數組,分割多個成長度大於等於3的連續的序列,問能不能分割成功。
開始的想法是,第一遍掃一下,依次枚舉3個連續的數作為一個分割,並記錄每個分割最后的一個數(為后期拓展所用)。
第二次掃描,看剩下的數能不能放到任何一個分割的后面。如果能,那么更新分割的最后一個值。
第三次掃描,看還有沒有剩下的數字,如果沒有那么返回true,否則false
看似天一無縫,卻始終過不了倒數第二個測試例子------> 179 / 180 test cases passed.
手寫了一個樣例 [1,2,3,4,5,5,5,6,6,7,7,8,9,10]
在處理的時候,按照上上面的套路(1,2,3)(4,5,6),(5,6,7),(7,8,9) 剩下 5和10, 5,和10 只能放在 3,6,7,9后面,10可以放在9后面,但是5沒有地方放,返回false。
可是 我們肉眼能找到(1,2,3,4,5)(5,6,7)(5,6,7)(8,9,10)這樣合法的分割,應該返回true。思路有瑕疵。其實我們思考的順序有錯誤,對於當前的數字x,我們應該先判斷x-1是否存在,如果存在就直接放上就好了,不存在的時候再構建一個長度為3個分割,如果長度為3的分割都構建不了,那么直接返回false就ok了。說道這里,這題目還是有貪心的味道的....
這里mp2[y]記錄以y作為i分割末尾的數量。
class Solution { public: bool isPossible(vector<int>& nums) { int n = nums.size(); //sort(nums.begin(), nums.end()); if (n < 3) return false; map<int, int>mp; for (int i = 0; i < n; ++i) mp[nums[i]]++; map<int, int>mp2; for (int i = 0; i < n; ++i) { int x = nums[i]; if (mp[x] <= 0) continue; if (mp2[x-1] > 0) { mp2[x]++, mp2[x-1]--, mp[x]--; } else if (mp[x+1] > 0 && mp[x+2] > 0) { mp[x]--, mp[x+1]--, mp[x+2]--; mp2[x+2]++; } else { return false; } } return true; } };