659. Split Array into Consecutive Subsequences

195 篇文章 0 订阅
问题描述

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:
The length of the input is in range of [1, 10000]

题目链接:

思路分析

判断一个数组中的数,有重复,可不可以分割成至少有三个元素的递增连续子序列。

这道题让我们将数组分割成多个连续递增的子序列,注意这里可能会产生歧义,实际上应该是分割成一个或多个连续递增的子序列,因为[1,2,3,4,5]也是正确的解。这道题就用贪婪解法就可以了,我们使用两个哈希表map,第一个map用来建立数字和其出现次数之间的映射freq,第二个用来建立可以加在某个连续子序列后的数字及其可以出现的次数之间的映射need。对于第二个map,举个例子来说,就是假如有个连,[1,2,3],那么后面可以加上4,所以就建立4的映射。这样我们首先遍历一遍数组,统计每个数字出现的频率,然后我们开始遍历数组,对于每个遍历到的数字,首先看其当前出现的次数,如果为0,则继续循环;如果need中存在这个数字的非0映射,那么表示当前的数字可以加到某个连的末尾,我们将当前数字的映射值自减1,然后将下一个连续数字的映射值加1,因为当[1,2,3]连上4后变成[1,2,3,4]之后,就可以连上5了;如果不能连到其他子序列后面,我们来看其是否可以成为新的子序列的起点,可以通过看后面两个数字的映射值是否大于0,都大于0的话,说明可以组成3连儿,于是将后面两个数字的映射值都自减1,还有由于组成了3连儿,在need中将末尾的下一位数字的映射值自增1;如果上面情况都不满足,说明该数字是单牌,只能划单儿,直接返回false。最后别忘了将当前数字的freq映射值自减1。

代码
class Solution {
    public boolean isPossible(int[] nums) {
        Map<Integer, Integer> frequency = new HashMap<>();
        Map<Integer, Integer> append = new HashMap<>();
        for (int n : nums){
            frequency.put(n, frequency.getOrDefault(n, 0) + 1);
        }
        for (int n : nums){
            if (frequency.get(n) == 0){
                continue;
            }
            else if (append.getOrDefault(n, 0) > 0){
                append.put(n, append.get(n) - 1);
                append.put(n + 1, append.getOrDefault(n + 1, 0) + 1);
            }
            else if (frequency.getOrDefault(n + 1, 0) > 0 && frequency.getOrDefault(n + 2, 0) > 0){
                frequency.put(n + 1, frequency.get(n + 1) - 1);
                frequency.put(n + 2, frequency.get(n + 2) - 1);
                append.put(n + 3, append.getOrDefault(n + 3, 0) + 1);
            }
            else{
                return false;
            }
            frequency.put(n, frequency.get(n) - 1);
        }
        return true;
    }
}

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)


反思
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值