leetcode 659. Split Array into Consecutive Subsequences

本文深入探讨了如何将一个升序排列的整数数组划分成若干子序列,每个子序列包含至少三个连续整数的问题。通过实例展示了算法的运行过程,并详细解释了使用两个HashMap来跟踪数字频率和可能的子序列连接点的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

数组中给出几个数,让把这些数划分成几个子序列,每个子序列中至少是3个连续的数字,可以多于3个,但是数字必须是连续的

思路:
每个数字要么自己开头创造一个新的子序列,要么接在现有子序列的后面

如果自己创造一个新的子序列,假设这个数是x,因为要求子序列中必须至少有3个连续的数字,所以x+1, x+2必须存在而且没有被其他子序列用完(使用次数>0)

如果接在现有子序列后面,还是假设这个数是x,那么x+1应该也可以接在这个后面,同时要把自己的使用次数-1

因为涉及到了使用次数,所以要保存每个数字对应的频率,所以用一个HashMap
同时如何判断是否能接在现有子序列后面,能接在多少个子序列后面,也是需要一个HashMap,保存一个可以接在现有子序列后面的数字及能接的子序列的个数

如果即不能接在现有子序列后面,又不能开创新子序列,直接返回false

**注意follow这个HashMap,刚开始的时候并没有保存可以接在子序列后面的数字,所以hashMap.get时,如果数字不存在,返回的是null而不是0,所以要用getOrDefault

    public boolean isPossible(int[] nums) {
        if (nums == null || nums.length < 3) {
            return false;
        }
        
        HashMap<Integer, Integer> freq = new HashMap<Integer, Integer>();
        HashMap<Integer, Integer> follow = new HashMap<Integer, Integer>();
        
        for (int num : nums) {
            freq.put(num, freq.getOrDefault(num, 0) + 1);
        }
        
        for (int num : nums) {
            if (freq.get(num) == 0) {  //already used..
                continue;
            }
            
            if (follow.getOrDefault(num, 0) > 0) {   //follow as a subsequnce..
                follow.put(num, follow.get(num) - 1);
                follow.put(num + 1, follow.getOrDefault(num + 1, 0) + 1);
            } else {   //start by self..
                if (freq.getOrDefault(num + 1, 0) > 0 && freq.getOrDefault(num + 2, 0) > 0) {   
                    freq.put(num + 1, freq.get(num + 1) - 1);
                    freq.put(num + 2, freq.get(num + 2) - 1);
                    follow.put(num + 3, follow.getOrDefault(num + 3, 0) + 1);
                } else {
                    return false;
                }
            }
            freq.put(num, freq.get(num) - 1);
        }
        return true;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值