leetcode 659. Split Array into Consecutive Subsequences

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

 

============================2018.12.23更新=========================

思路如下,但不用优先队列,记录前一个数字,和子子串长度的计数p1,p2,p3。和后一个子串长度c1,c2,c3。代码没整理,思路是和以前一样。时间复杂度O(n),空间复杂度O(1)

class Solution {
    public boolean isPossible(int[] nums) {
        int pre=nums[0],p1=1,p2=0,p3=0;
        int c1=0,c2=0,c3=0;
        for(int i=1;i<nums.length;i++){
            if(nums[i]==pre){
                p1++;
            }
            else if(nums[i]==pre+1){//下个
                if(p1>0){
                    p1--;
                    c2++;
                }else if(p2>0){
                    c3++;
                    p2--;
                }else if(p3>0){
                    p3--;
                    c3++;
                }else{
                    c1++;
                }
            }else if(nums[i]==nums[i-1]+1){//下下个
                if(p1>0||p2>0) return false;
                pre=nums[i-1];
                p1=c1;
                p2=c2;
                p3=c3;
                c1=0;
                c2=0;
                c3=0;
                if(p1>0){
                    p1--;
                    c2++;
                }else if(p2>0){
                    c3++;
                    p2--;
                }else if(p3>0){
                    p3--;
                    c3++;
                }else{
                    c1++;
                }
            }else if(nums[i]>nums[i-1]+1){//断开
                if(p1>0||p2>0||c1>0||c2>0) return false;
                pre=nums[i];
                p1=1;
                p2=0;
                p3=0;
                c1=0;
                c2=0;
                c3=0;
            }
        }
        if(p1>0||p2>0||c1>0||c2>0) return false;
        return true;
    }
}

==================================================================

 

第一次做优先队列的题,没有想到要用优先队列。参考了别人的思路。
 

整理一下思考步骤:首先碰到这种题,应该要想到要定义几个容器存放子序列,再想到什么时候划分子序列,1.总列的开头;2.到连续相等数的时候;3与前面间断的数。(其他情况可排除),再观察容器只用存放子序列最后一个数和子序列当前的长度就可以了。当遍历到一个新的数时,要快速找到当前数小于1的数。所以把子序列的最后一个数考虑存放到hashmap中,value可能代表多个子序列的长度,可以考虑用数组。但是每次要取出长度最短的子序列,所以这里要采用优先队列(一个特殊的数组)。到这里上面3种情况可以转化为:遍历总数组的时候是否能找到其他子序列中存在最后一个数比它小1。

分为4种情况:当遍历到某数num是,是否存在结尾num-1的子序列,是否存在num的子序列。最后检查所有子序列的长度。

class Solution {
    //通用思路,要定义几个容器装下每个组,怎么分组?在遍历的时候,如果在已存在分组中没找到连续的就创建新分组,有两个连续就添加到最短的分组
    //每个容器存最后的一个数,和这容器的遍历到的当前个数,map集合,key为存在容器中最后一个数,value为一个集合装下在某最后一个数下的 所有子数组的个数
    //优先队列看做一个特殊的集合(类似特殊的数组)
    public boolean isPossible(int[] nums) {
        if(nums.length==0){
            return false;
        }
        HashMap<Integer,PriorityQueue<Integer>> map=new HashMap<>();
        for(int i=0;i<nums.length;i++){
            if(map.get(nums[i]-1)==null){//存在小于1的数
                if(map.get(nums[i])!=null){
                    PriorityQueue<Integer> pq0=map.get(nums[i]);
                    pq0.add(1);
                }else{
                    PriorityQueue<Integer> pq0=new PriorityQueue<>();
                    pq0.add(1);//长度
                    map.put(nums[i],pq0);
                }
            }else{            
                PriorityQueue<Integer> pq=map.get(nums[i]-1);//先取出上一个的长度,再在后面一个存长度+1
                int len=pq.isEmpty()?0:pq.poll();
                if(map.get(nums[i])==null){
                    PriorityQueue<Integer> pq1=new PriorityQueue<>();
                    pq1.add(len+1);
                    map.put(nums[i],pq1);
                }else{
                    PriorityQueue<Integer> pq1=map.get(nums[i]);
                    pq1.add(len+1);
                }
            }    
        }
        for(int i:map.keySet()){
            for(int j:map.get(i)){
                if(j<3){
                    return false;
                }
            }
        }
        return true;
    }
}

之后看了leetcode讨论区,还有更好的方法。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值