分割数组为连续子序列

题目详情

给你一个按升序排序的整数数组num(可能包含重复数字),请你将它们分割成一个或多个长度至少为3的子序列,其中每个子序列都由连续整数组成。如果可完成上述分割,则返回true;否则,返回false。

示例1

输入:{1, 2, 3, 4, 5}
输出:True
解释:
你可以分割出这样两个连续子序列:
1, 2, 3
3, 4, 5

示例2:

输入:{1, 2, 3, 3, 4, 4, 5, 5}
输出:True
解释:
你可以分割出这样两个连续子序列:
1, 2, 3, 4, 5
3, 4, 5

示例3:

输入:{1, 2, 3, 4, 4, 5}
输出:False

思路:

因为数组为升序数组,且子序列需要连续整数,可以将数组转换为统计关键字数量数组,使用统计数组进行排列。
分割数组不要求计算可分割数量,故而时将子序列按最大长度分割,当元素为最后一种元素或元素统计数比下一个元
素统计数大的时候分割

实现:

public static boolean subSequence(int[] array) {
	// 子序列最小长度
    int standard = 3; 

	// 原数组不达到子序列最小长度
    if (array.length < standard) {
        return false;
    }
    // 统计数组 长度为array.length 防止数组下标上限越界
    int[] copy = new int[array.length];
	// 统计
    for (int i : array) {
        copy[i - array[0]]++;
    }

    // 获取最后一个非0数字 copy初始化的时候所有元素为0
    int lastIndex = copy.length - 1;
    while (copy[lastIndex] == 0) {
        lastIndex--;
    }
	// 元素种数不达到子序列最小长度
    if (lastIndex < standard - 1) {
        return false;
    }
	// 判断元素是否为连续不间断
    for (int i = 0; i <= lastIndex; i++) {
        if (copy[i] == 0) {
            return false;
        }
    }
	// first为每一个子序列起始位置,count为子序列长度
    int first = 0, count;
    // 辅助变量,判断下一个子序列起始位置是否找到
    boolean flag;
    // 因为后续每一次子序列获取元素时,统计数组对应元素的统计数会减-,所以最后一个元素统计数为0时数组分割完成
    while (copy[lastIndex] != 0) {
        count = 0;
        flag = false;
        // 	从子序列起始位置找到所有子序列元素
        for (int i = first; i <= lastIndex; i++) {
			// 数量不为1 下一个子序列起始位置则是这个一个元素 
            if (copy[i] != 1 && !flag) {
                flag = true;
                first = i;
            }
            // 子序列数量+1
            count++;
            copy[i]--;
            
            // 当元素为最后一种元素或元素统计数比下一个元素统计数大(=是因为之前已经-1,所以存在=的情况)的时候完成分割
            if (i != lastIndex && copy[i] >= copy[i + 1]) {
                break;
            }
        }
        // 判断是否符合数量要求
        if (count < standard) {
            return false;
        }
    }
    return true;
}

验证:

public static void main(String[] args) {
    System.out.println(subSequence(new int[]{1, 2, 3, 3, 4, 5}));
    System.out.println(subSequence(new int[]{}));
    System.out.println(subSequence(new int[]{1, 2, 3, 3, 4, 4, 5, 5}));
    System.out.println(subSequence(new int[]{1, 2, 3, 4, 4, 5}));
    System.out.println(subSequence(new int[]{1, 2, 3, 3, 4, 4, 5}));
    System.out.println(subSequence(new int[]{1, 2, 3, 3, 4, 4, 4, 5, 5, 6}));
    System.out.println(subSequence(new int[]{1, 2, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6}));
}

结果:

true
false
true
false
true
true
true
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值