目录
题目解析 | 如何在数组中顺序匹配多个子数组?
题目描述
给定一个二维整数数组 groups
和一个一维整数数组 nums
,判断是否能够依次在 nums
中找到 groups
中的每一个子数组,且这些子数组在 nums
中是顺序出现且互不重叠的。
换句话说,是否存在一组索引,使得 nums
中连续的子数组分别等于 groups
中的每个数组,并且这些子数组的顺序与 groups
中相同。
输入
groups
:二维整数数组,每个元素是一个整数数组。nums
:一维整数数组。
输出
- 返回布尔值
True
或False
:
-
- 如果能够顺序匹配所有
groups
的子数组,则返回True
。 - 否则返回
False
。
- 如果能够顺序匹配所有
解题分析
这道题的核心是“顺序匹配多个子数组”,且每个匹配都不能重叠。具体要点包括:
- 顺序匹配:必须依照
groups
中子数组的顺序,依次在nums
中找到对应的子数组。 - 不重叠:每次匹配成功后,下一次搜索必须从上次匹配结束的位置继续,不能重用之前已经匹配过的元素。
- 连续匹配:每个子数组匹配时必须是连续的片段。
解题方法
思路
- 维护一个指针
start
,表示在nums
中开始匹配的起始位置。 - 对
groups
中每个子数组group
:
-
- 从
start
位置开始,遍历nums
,寻找一段长度为len(group)
的连续子数组与group
完全相同。 - 如果找到,更新
start
为当前匹配段的末尾位置(即start += len(group)
),然后继续匹配下一个group
。 - 如果没有找到,说明无法完整匹配,直接返回
False
。
- 从
- 如果所有
group
都能匹配成功,返回True
。
代码实现
from typing import List
class Solution:
def canChoose(self, groups: List[List[int]], nums: List[int]) -> bool:
start = 0 # nums中开始搜索的位置
for group in groups:
found = False
while start + len(group) <= len(nums):
if nums[start:start + len(group)] == group:
found = True
start += len(group) # 下一轮搜索从当前匹配子数组结尾开始
break
start += 1
if not found:
return False
return True
代码解析
- 变量
start
:标记下一轮在nums
中搜索的起始索引,防止子数组重叠。 - 双重循环结构:
-
- 外循环遍历每个
group
。 - 内循环从
start
到len(nums)
中逐个位置尝试匹配当前group
。
- 外循环遍历每个
- 匹配判断:使用切片比较
nums[start:start+len(group)]
和group
。 - 更新指针:一旦找到匹配,
start
指针前移,避免重复使用元素。 - 返回结果:
-
- 如果所有
group
都匹配成功,返回True
。 - 如果有任何一个
group
匹配失败,返回False
。
- 如果所有
时间和空间复杂度分析
- 设:
-
m
=len(groups)
,组数n
=len(nums)
,数组长度k
= 最大子数组长度
时间复杂度
- 最坏情况下,内层循环每次移动
start
一步,最多遍历n
次。 - 每次比较子数组长度为
k
。 - 总体时间复杂度约为 O(m * n * k),实际中由于指针移动和提前中断,效率会比理论上的低。
空间复杂度
- 只使用了常数额外空间(指针和标志位),空间复杂度为 O(1)。
示例说明
示例1
groups = [[1, -1, -1], [3, -2, 0]]
nums = [1, -1, 0, 1, -1, -1, 3, -2, 0]
过程:
- 找
groups[0] = [1, -1, -1]
在nums
中连续出现的位置:
-
- 从索引0开始:
[1, -1, 0]
不匹配 - 索引1:
[-1, 0, 1]
不匹配 - 索引2:
[0, 1, -1]
不匹配 - 索引3:
[1, -1, -1]
匹配成功,更新start=6
- 从索引0开始:
- 找
groups[1] = [3, -2, 0]
在nums
中从索引6开始找:
-
- 索引6:
[3, -2, 0]
匹配成功,完成所有匹配。
- 索引6:
返回 True
示例2
groups = [[10, -2], [1, 2, 3, 4]]
nums = [1, 2, 3, 4, 10, -2]
- 查找
[10, -2]
:
-
- 从索引0开始:
[1, 2]
不匹配 - 索引1:
[2, 3]
不匹配 - 索引2:
[3, 4]
不匹配 - 索引3:
[4, 10]
不匹配 - 索引4:
[10, -2]
匹配成功,start = 6
- 从索引0开始:
- 查找
[1, 2, 3, 4]
:
-
start=6
已经超过nums
长度,无法匹配,返回False
总结
这道题的关键在于:
- 维护搜索起点,保证子数组不重叠。
- 顺序匹配,不能乱序查找。
- 使用切片直接比较数组是否相等,简洁有效。
实现思路简单直观,时间复杂度在中等范围,适合这类匹配问题。