0659. 分割数组为连续子序列
大约 3 分钟
---
0659. 分割数组为连续子序列
- 标签:贪心、数组、哈希表、堆(优先队列)
- 难度:中等
题目链接
题目大意
描述:
给定一个按「非递减顺序」排列的整数数组 。
要求:
判断是否能在将 分割成 一个或多个子序列 的同时满足下述两个条件:
- 每个子序列都是一个「连续递增序列」(即,每个整数「恰好」比前一个整数大 )。
- 所有子序列的长度「至少」为 。
如果可以分割 并满足上述条件,则返回 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解题思路
思路 1:贪心 + 哈希表
这道题目要求将数组分割成若干个长度至少为 3 的连续递增子序列。使用贪心策略:优先将当前数字接到已有的子序列后面,如果不能接到已有子序列,则尝试创建新的子序列。
- 使用哈希表 记录每个数字的剩余可用次数。
- 使用哈希表 记录以某个数字结尾的子序列需要的下一个数字的数量。
- 遍历数组中的每个数字 :
- 如果 ,说明该数字已经被使用完,跳过。
- 如果 ,说明存在以 结尾的子序列需要 ,将 接到该子序列后面:
- 减 1, 减 1。
- 加 1(该子序列现在需要 )。
- 否则,尝试创建新的子序列 :
- 检查 和 是否大于 0。
- 如果可以创建,将这三个数字的频率减 1,并将 加 1。
- 如果不能创建,返回 。
- 如果所有数字都能成功分配,返回 。
思路 1:代码
class Solution:
def isPossible(self, nums: List[int]) -> bool:
from collections import defaultdict
freq = defaultdict(int) # 记录每个数字的剩余可用次数
need = defaultdict(int) # 记录以某个数字结尾的子序列需要的下一个数字的数量
# 统计每个数字的频率
for num in nums:
freq[num] += 1
for num in nums:
if freq[num] == 0:
continue
# 优先将 num 接到已有的子序列后面
if need[num] > 0:
need[num] -= 1
freq[num] -= 1
need[num + 1] += 1
# 尝试创建新的子序列 [num, num+1, num+2]
elif freq[num + 1] > 0 and freq[num + 2] > 0:
freq[num] -= 1
freq[num + 1] -= 1
freq[num + 2] -= 1
need[num + 3] += 1
else:
# 无法分配当前数字
return False
return True思路 1:复杂度分析
- 时间复杂度:,其中 是数组的长度。需要遍历数组两次。
- 空间复杂度:,需要使用两个哈希表存储频率和需求信息。