[LeetCode] 659. Split Array into Consecutive Subsequences 將數組分割成連續子序列


 

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:

  1. The length of the input is in range of [1, 10000]

 

博主第一眼看到這題,心想,我去,這不就是打牌么,什么挖坑,拐3,紅桃4啊,3個起連,有時候排組合的好,就不用划單兒。這道題讓將數組分割成多個連續遞增的子序列,注意這里可能會產生歧義,實際上應該是分割成一個或多個連續遞增的子序列,因為 [1,2,3,4,5] 也是正確的解。這道題就用貪婪解法就可以了,使用兩個 HashMap,第一個 HashMap 用來建立數字和其出現次數之間的映射 freq,第二個用來建立可以加在某個連續子序列后的數字與其可以出現的次數之間的映射 need。對於第二個 HashMap,舉個例子來說,就是假如有個連牌,比如對於數字1,此時檢測數字2和3是否存在,若存在的話,表明有連牌 [1,2,3] 存在,由於后面可以加上4,組成更長的連牌,所以不管此時牌里有沒有4,都可以建立 4->1 的映射,表明此時需要一個4。這樣首先遍歷一遍數組,統計每個數字出現的頻率,然后開始遍歷數組,對於每個遍歷到的數字,首先看其當前出現的次數,如果為0,則繼續循環;如果 need 中存在這個數字的非0映射,那么表示當前的數字可以加到某個連的末尾,將當前數字在 need 中的映射值自減1,然后將下一個連續數字的映射值加1,因為當 [1,2,3] 連上4后變成 [1,2,3,4] 之后,就可以連上5了,說明此時還需要一個5;如果不能連到其他子序列后面,則來看其是否可以成為新的子序列的起點,可以通過看后面兩個數字的映射值是否大於0,都大於0的話,說明可以組成3連兒,於是將后面兩個數字的映射值都自減1,還有由於組成了3連兒,在 need 中將末尾的下一位數字的映射值自增1;如果上面情況都不滿足,說明該數字是單牌,只能划單兒,直接返回 false。最后別忘了將當前數字的 freq 映射值自減1。退出 for 循環后返回 true,參見代碼如下:

 

class Solution {
public:
    bool isPossible(vector<int>& nums) {
        unordered_map<int, int> freq, need;
        for (int num : nums) ++freq[num];
        for (int num : nums) {
            if (freq[num] == 0) continue;
            if (need[num] > 0) {
                --need[num];
                ++need[num + 1];
            } else if (freq[num + 1] > 0 && freq[num + 2] > 0) {
                --freq[num + 1];
                --freq[num + 2];
                ++need[num + 3];
            } else return false;
            --freq[num];
        }
        return true;
    }
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/659

 

類似題目:

Top K Frequent Words

 

參考資料:

https://leetcode.com/problems/split-array-into-consecutive-subsequences/

https://leetcode.com/problems/split-array-into-consecutive-subsequences/discuss/106496/Java-O(n)-Time-O(n)-Space

https://leetcode.com/problems/split-array-into-consecutive-subsequences/discuss/106493/C%2B%2B-O(n)-solution-two-pass

https://leetcode.com/problems/split-array-into-consecutive-subsequences/discuss/106495/Java-O(n)-time-and-O(1)-space-solution-greedily-extending-shorter-subsequence

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM