1764. 通过连接另一个数组的子数组得到一个数组

目录

题目解析 | 如何在数组中顺序匹配多个子数组?

题目描述

输入

输出

解题分析

解题方法

思路

代码实现

代码解析

时间和空间复杂度分析

时间复杂度

空间复杂度

示例说明

示例1

示例2

总结


题目解析 | 如何在数组中顺序匹配多个子数组?

题目描述

给定一个二维整数数组 groups 和一个一维整数数组 nums,判断是否能够依次在 nums 中找到 groups 中的每一个子数组,且这些子数组在 nums 中是顺序出现且互不重叠的。

换句话说,是否存在一组索引,使得 nums 中连续的子数组分别等于 groups 中的每个数组,并且这些子数组的顺序与 groups 中相同。


输入

  • groups:二维整数数组,每个元素是一个整数数组。
  • nums:一维整数数组。

输出

  • 返回布尔值 TrueFalse
    • 如果能够顺序匹配所有 groups 的子数组,则返回 True
    • 否则返回 False

解题分析

这道题的核心是“顺序匹配多个子数组”,且每个匹配都不能重叠。具体要点包括:

  1. 顺序匹配:必须依照 groups 中子数组的顺序,依次在 nums 中找到对应的子数组。
  2. 不重叠:每次匹配成功后,下一次搜索必须从上次匹配结束的位置继续,不能重用之前已经匹配过的元素。
  3. 连续匹配:每个子数组匹配时必须是连续的片段。

解题方法

思路

  • 维护一个指针 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
    • 内循环从 startlen(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
  • groups[1] = [3, -2, 0]nums 中从索引6开始找:
    • 索引6:[3, -2, 0] 匹配成功,完成所有匹配。

返回 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
  • 查找 [1, 2, 3, 4]
    • start=6 已经超过 nums 长度,无法匹配,返回 False

总结

这道题的关键在于:

  • 维护搜索起点,保证子数组不重叠。
  • 顺序匹配,不能乱序查找。
  • 使用切片直接比较数组是否相等,简洁有效。

实现思路简单直观,时间复杂度在中等范围,适合这类匹配问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值