[LeetCode] 贪心算法之 Split Array into Consecutive Subsequence

题目

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

分析

这题的思路有多种,O(n2)的就不在考虑范围内了,主要考虑如何降到O(nlogn)甚至O(n)。这题的思路中有个问题,就在于你是要优先扩展subsequence的数量,还是长度的问题。实际上是需要尽量保证长度的,不然有些example会存在优先数量不能过,但是优先长度能过的情况。
思路上就是对于每个num,检查目前每个已存在的subsequence有没有最大值为num-1的这种序列,如果有就加入这个序列。否则,就检查还没有被放进subsequence的值中有没有num+1和num+2,如果有一个没有,那么就直接返回false。

时间复杂度分析

需要扫描array两遍,采用hash方法存储,插入删除是常数时间(如果采用unordered_multiset可能只用扫描一遍,直接构造函数添加进去),总的时间复杂度是O(n)。

代码

class Solution {
public:
    bool isPossible(vector<int>& nums) {
        // count is used to keep the frequence of each num
        // subsequence is mapped from the max number of each subsequence to 
        // its correlated frequency
        unordered_map<int,int> count, subsequence;
        for (int i : nums) count[i]++;
        for (int i : nums){
            if (!count[i]) continue;
            count[i]--;
            // condition that if having a subsequence with max num is i-1
            if (subsequence[i - 1] > 0) {
                subsequence[i - 1]--;
                subsequence[i]++;
            }
            // condition that start a new subsequence
            else if (count[i + 1] && count[i + 2]){ 
                count[i + 1]--;
                count[i + 2]--;
                subsequence[i + 2]++;
            }
            else return false;
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值