1. 程式人生 > 實用技巧 >[LeetCode] 659. Split Array into Consecutive Subsequences

[LeetCode] 659. Split Array into Consecutive Subsequences

Given an arraynumssorted in ascending order, returntrueif and only if you can split it into 1 or more subsequences such that each subsequence consists of consecutive integersand has length at least 3.

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

Constraints:

  • 1 <= nums.length <= 10000

分割陣列為連續子序列。

給你一個按升序排序的整數陣列 num(可能包含重複數字),請你將它們分割成一個或多個子序列,其中每個子序列都由連續整陣列成且長度至少為 3 。

如果可以完成上述分割,則返回 true ;否則,返回 false 。

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/split-array-into-consecutive-subsequences
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

這道題有兩種思路,一種是貪心,一種涉及到最小堆。我這裡暫時提供一個最小堆的做法。

題目的目標是需要湊若干個長度起碼為3的連續整數子陣列,所以我們一開始肯定是要遍歷input裡的每個數字,並且用hashmap<num, pq>為每個unique的數字建立一個最小堆,意思是記錄每個以 num 為結尾的子陣列的個數。最小堆裡面放的是以num為結尾的子陣列的長度,所以長度最短的子陣列在堆頂。

開始遍歷 input 陣列,當遇到一個數字 num 的時候,放入hashmap,同時去看一下hashmap裡面是否有 num - 1,如果有,需要計算一下以num - 1 為結尾的子陣列的長度是多少,這樣 num 才能被疊加到這個長度上去。如果這個 num 能被疊加,則需要去hashmap裡對num - 1 的value--,直到去掉這個key為止。如果num - 1 不存在,則說明當前的 num 應該是一個子陣列的起點,則直接把他放入hashmap即可。

在遍歷完所有元素之後,我們再次遍歷hashmap的keyset,如果其中有任何一個key的堆頂元素小於3,則說明存在以某個數字為結尾的子陣列,其長度不足3,這不符合題意,返回false。

時間O(nlogn) - 其中O(n)是遍歷每個元素,當子陣列長度有變化的時候,往pq中加入元素的複雜度是O(logn),所以整體還是O(nlogn)

空間O(n)

Java實現

 1 class Solution {
 2     public boolean isPossible(int[] nums) {
 3         // <lastNumber, pq<length>>
 4         // 以num為結尾的子陣列的長度
 5         // pq是最小堆,最短的子陣列長度在堆頂
 6         HashMap<Integer, PriorityQueue<Integer>> map = new HashMap<>();
 7         for (int num : nums) {
 8             if (!map.containsKey(num)) {
 9                 map.put(num, new PriorityQueue<>());
10             }
11             if (map.containsKey(num - 1)) {
12                 int prevLength = map.get(num - 1).poll();
13                 if (map.get(num - 1).isEmpty()) {
14                     map.remove(num - 1);
15                 }
16                 map.get(num).offer(prevLength + 1);
17             } else {
18                 map.get(num).offer(1);
19             }
20         }
21 
22         for (Integer key : map.keySet()) {
23             if (map.get(key).peek() < 3) {
24                 return false;
25             }
26         }
27         return true;
28     }
29 }

LeetCode 題目總結