659. 分割数组为连续子序列

19 篇文章 0 订阅
这篇博客探讨了如何利用哈希表实现贪心算法,以解决寻找特定长度子序列的问题。通过两个哈希表,一个记录数组中每个数字的剩余次数,另一个存储作为子序列结尾的数字数量。在遍历数组时,根据哈希表更新子序列信息,确保满足条件。如果所有元素都能被包含在满足条件的子序列中,则返回true,否则返回false。
摘要由CSDN通过智能技术生成

getOrDefault使用方法
Method Returns
The getOrDefault() method returns the value to which the specified key is mapped, or defaultValue if this map contains no mapping for the key.
当HashMap集合中有这个key时,如果存在则return it,如果没有就使用默认值defaultValue
贪心算法
时间复杂度:O(n)
空间复杂度:O(n)
使用两个哈希表,第一个哈希表存储数组中的每个数字的剩余次数,第二个哈希表存储数组中的每个数字作为结尾的子序列的数量。

初始时,每个数字的剩余次数即为每个数字在数组中出现的次数,因此遍历数组,初始化第一个哈希表。

在初始化第一个哈希表之后,遍历数组,更新两个哈希表。只有当一个数字的剩余次数大于 00 时,才需要考虑这个数字是否属于某个子序列。假设当前元素是 xx,进行如下操作。

首先判断是否存在以 x-1x−1 结尾的子序列,即根据第二个哈希表判断 x-1x−1 作为结尾的子序列的数量是否大于 00,如果大于 00,则将元素 xx 加入该子序列中。由于 xx 被使用了一次,因此需要在第一个哈希表中将 xx 的剩余次数减 11。又由于该子序列的最后一个数字从 x-1x−1 变成了 xx,因此需要在第二个哈希表中将 x-1x−1 作为结尾的子序列的数量减 11,以及将 xx 作为结尾的子序列的数量加 11。

否则,xx 为一个子序列的第一个数,为了得到长度至少为 33 的子序列,x+1x+1 和 x+2x+2 必须在子序列中,因此需要判断在第一个哈希表中 x+1x+1 和 x+2x+2 的剩余次数是否都大于 00。

当 x+1x+1 和 x+2x+2 的剩余次数都大于 00 时,可以新建一个长度为 33 的子序列 [x,x+1,x+2][x,x+1,x+2]。由于这三个数都被使用了一次,因此需要在第一个哈希表中将这三个数的剩余次数分别减 11。又由于该子序列的最后一个数字是 x+2x+2,因此需要在第二个哈希表中将 x+2x+2 作为结尾的子序列的数量加 11。

否则,无法得到长度为 33 的子序列 [x,x+1,x+2][x,x+1,x+2],因此无法完成分割,返回 false。

如果整个数组遍历结束时,没有遇到无法完成分割的情况,则可以完成分割,返回true。

class Solution {
    public boolean isPossible(int[] nums) {
        Map<Integer, Integer> countMap = new HashMap<Integer, Integer>();
        Map<Integer, Integer> endMap = new HashMap<Integer, Integer>();
        for (int x : nums) {
            int count = countMap.getOrDefault(x, 0) + 1;
            countMap.put(x, count);
        }
        for (int x : nums) {
            int count = countMap.getOrDefault(x, 0);
            if (count > 0) {
                int prevEndCount = endMap.getOrDefault(x - 1, 0);
                if (prevEndCount > 0) {
                    countMap.put(x, count - 1);
                    endMap.put(x - 1, prevEndCount - 1);
                    endMap.put(x, endMap.getOrDefault(x, 0) + 1);
                } else {
                    int count1 = countMap.getOrDefault(x + 1, 0);
                    int count2 = countMap.getOrDefault(x + 2, 0);
                    if (count1 > 0 && count2 > 0) {
                        countMap.put(x, count - 1);
                        countMap.put(x + 1, count1 - 1);
                        countMap.put(x + 2, count2 - 1);
                        endMap.put(x + 2, endMap.getOrDefault(x + 2, 0) + 1);
                    } else {
                        return false;
                    }
                }
            }
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值