[LeetCode] 659. Split Array into Consecutive Subsequences

Given an array nums sorted in ascending order, return true if and only if you can split it into 1 or more subsequences such that each subsequence consists of consecutive integers and 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这道题有两种思路,一种是贪心,一种涉及到最小堆。我这里暂时提供一个最小堆的做法。类似题目有846和1296。

题目的目标是需要凑若干个长度起码为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 }

 

相关题目

659. Split Array into Consecutive Subsequences

846. Hand of Straights

1296. Divide Array in Sets of K Consecutive Numbers

LeetCode 题目总结

posted @ 2020-12-04 11:52  CNoodle  阅读(177)  评论(0编辑  收藏  举报