zoukankan      html  css  js  c++  java
  • [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 题目总结

  • 相关阅读:
    springboot事物和事物回滚
    MyBatis Sql语句中的转义字符
    使用 vagrant新建Linux虚拟机
    Centos 6.7 安装mongodb
    阿里云windows server 2012 TIME_WAIT CLOSE_WAIT
    使用Eclipse打jar包 包含依赖jar包
    linux crontab定时器
    mysql 存储过程学习笔记
    oracle windows 新建用户授权 导出导入bmp文件
    解决hash冲突的方法
  • 原文地址:https://www.cnblogs.com/cnoodle/p/14085065.html
Copyright © 2011-2022 走看看