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]

解題思路

剛開始的時候老是想着在掃描數組時,每掃描到一個新的數字都要確定以該數字爲開頭的一個連續序列。其實根本不需要掃到一個數字就確定一個連續序列,而是可以在掃描數組的過程中,把數字逐一地添加到未完整的連續序列中,動態地往連續序列中添加數據。整個算法過程如下:

  1. 維護兩個哈希表 frequencytails. frequency 表記錄數組中每個數字出現的次數,而 tails 表則記錄以某個數字結尾的連續序列的個數,比如 tails[key] 的值爲2,表示以數字 key 爲結尾的連續序列共有兩個。

  2. 第一次掃描數組,把數組中每個數字的出現次數記錄到 frequency 表中。

  3. 第二次掃描數組,對掃描到的每一個數字 num,如果 tails[num - 1] > 0 ,說明存在以 num - 1 爲結尾的連續序列,則把數字 num 添加到該連續序列中:tails[num - 1]--; tails[num]++。可能有人會擔心 num可能是另一個連續序列的開始數字而不應該加入到 tails[num - 1] 的連續序列中,但是任意以 num 爲開始數組的連續序列都可以與 tails[num - 1] 的連續序列合併:比如 [1, 2, 3][4, 5, 6] 兩個連續序列是可以合併成 [1, 2, 3, 4, 5, 6] 這個大的連續序列的,這對於結果是沒有影響的;如果 tails[num - 1] == 0 ,此時我們就需要以 num 爲開始數字建立一個新的連續序列。而一個連續序列至少包含 3 個數字,因此還要檢查 num + 1num + 2 這兩個數字是否存在,如果不存在,則直接 return false ,否則,新建以 num + 2 數字爲結尾的連續序列。

  4. 如果上述過程能進行到最後,說明所有連續序列都能夠找出來,則直接 return true

C++代碼實現

class Solution {
public:
    bool isPossible(vector<int>& nums) {
        unordered_map<int, int> frequency, tails;

        for (int &num : nums) { frequency[num]++; }
        for (int &num : nums) {
            // 如果 frequency[num] <= 0,說明在上一輪循環中新建了
            // 一個包含當前數字 num 的連續序列,直接跳過掃描下一個數字
            if (frequency[num] <= 0) { continue; }
            frequency[num]--;

            if (tails[num - 1] > 0) {
                tails[num - 1]--;
                tails[num]++;
            } else if (frequency[num + 1] && frequency[num + 2]) {
                // 新建連續序列,要把包含進新序列的數字的出現次數也減 1
                frequency[num + 1]--;
                frequency[num + 2]--;
                tails[num + 2]++;
            } else {
                return false;
            }
        }

        return true;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章