开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 26 天,点击查看活动详情
题目:LeetCode
给你一个按 非递减顺序 排列的整数数组 nums 。
请你判断是否能在将 nums 分割成 一个或多个子序列 的同时满足下述 两个 条件:
- 每个子序列都是一个 连续递增序列(即,每个整数 恰好 比前一个整数大 1 )。
- 所有子序列的长度 至少 为
3****。
如果可以分割 nums 并满足上述条件,则返回 true ;否则,返回 false 。
示例 1:
输入: nums = [1,2,3,3,4,5]
输出: true
解释: nums 可以分割成以下子序列:
[1,2,3,3,4,5] --> 1, 2, 3
[1,2,3,3,4,5] --> 3, 4, 5
示例 2:
输入: nums = [1,2,3,3,4,4,5,5]
输出: true
解释: nums 可以分割成以下子序列:
[1,2,3,3,4,4,5,5] --> 1, 2, 3, 4, 5
[1,2,3,3,4,4,5,5] --> 3, 4, 5
示例 3:
输入: nums = [1,2,3,4,4,5]
输出: false
解释: 无法将 nums 分割成长度至少为 3 的连续递增子序列。
提示:
-1000 <= nums[i] <= 1000nums按非递减顺序排列
解题思路
根据题意分析: 遍历nums元素时,分别记录1、2、3个以上(含)连续值的子串数量(oneCount,towCount,moreThreeCount),初始化都为0;
- 统计nums[i]元素值出现的次数标记为curCount; 优先将 curCount 个值 连接到 1,2个连续值的子串上;
- 若有剩余,连接到3个以上(含)个连续值的子串;
- 若还有剩余,生成1个连续值的子串;连接后,更新对应的 count 值(迁移更新)。若不足,直接返回false。
代码实现
public boolean isPossible(int[] nums) {
// 超过3个的连续值数量
int moreThreeCount = 0;
// 1个连续数量
int oneCount = 0;
// 2个连续数量
int towCount = 0;
//
int last = 0;
for (int i = 0; i < nums.length;) {
int start = i;
for (; start < nums.length && nums[start] == nums[i]; start++) {
}
int curCount = start - i;
if (i == 0 || nums[i] != last + 1) {
// 不连续
if (oneCount > 0 || towCount > 0) {
return false;
}
oneCount = curCount;
towCount = 0;
moreThreeCount = 0;
} else {
// 连续
if (curCount < oneCount + towCount) {
return false;
}
// oneCount 临时存储
int temp = curCount - (moreThreeCount + oneCount + towCount);
moreThreeCount = towCount + Math.min(moreThreeCount, curCount - (oneCount + towCount));
towCount = oneCount;
oneCount = temp < 0 ? 0 : temp;
//System.out.println(curCount + "---"+ i+"---"+oneCount+", " + towCount +", "+ moreThreeCount);
}
last = nums[i];
i = start;
}
return oneCount == 0 && towCount == 0;
}
运行结果
复杂度分析
- 空间复杂度:
- 时间复杂度:
在掘金(JUEJIN) 一起分享知识, Keep Learning!