You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在数组A中查找数组B的所有出现位置(含起止索引)

在数组A中查找数组B的所有出现实例(获取起止索引)

嘿,这个问题在数组处理场景里挺常见的,我来分享两种靠谱的解法,从易理解的暴力滑动窗口到高效的KMP算法,你可以根据数据规模来选~

基础解法:滑动窗口暴力匹配

核心思路就是把数组B当作一个固定大小的窗口,在数组A上逐个滑动,每次比对窗口内的子数组是否和B完全一致,匹配成功就记录起止索引。

步骤拆解

  • 边界判断:如果B的长度比A长,或者B是空数组,直接返回空结果(毕竟不可能有匹配)。
  • 确定滑动范围:窗口大小等于B的长度,A中有效起始索引的范围是0到len(A) - len(B)(包含),超过这个范围就剩不下足够的元素匹配B了。
  • 逐个比对:对每个起始索引i,取出A中从i到i+len(B)-1的子数组,和B比对;匹配成功就记录start_index = i,end_index = i + len(B) - 1。

Python 代码示例

def find_all_occurrences(A, B):
    occurrences = []
    len_A, len_B = len(A), len(B)
    
    # 处理边界情况
    if len_B == 0 or len_B > len_A:
        return occurrences
    
    window_size = len_B
    # 遍历所有可能的起始位置
    for i in range(len_A - window_size + 1):
        # 取出当前窗口的子数组
        current_window = A[i:i+window_size]
        if current_window == B:
            occurrences.append({
                "start_index": i,
                "end_index": i + window_size - 1
            })
    return occurrences

# 测试用例
A = [1, 2, 3, 2, 3, 4, 2, 3]
B = [2, 3]
print(find_all_occurrences(A, B))
# 输出: [{'start_index': 1, 'end_index': 2}, {'start_index': 3, 'end_index': 4}, {'start_index': 6, 'end_index': 7}]

这个方法的优点是逻辑简单、容易实现,适合小规模数组;缺点是时间复杂度为O(n*m)(n是A的长度,m是B的长度),数据量大的时候效率会下降。

优化解法:KMP算法(适合大数据量)

如果数组A和B的长度都很大,暴力匹配的效率就不够看了,这时候可以用KMP算法来优化,时间复杂度能降到O(n+m)。

核心逻辑

KMP的关键是预处理数组B,生成一个「前缀函数(部分匹配表)」,记录B中每个位置的最长相等前后缀长度。这样在比对A的时候,一旦出现不匹配的情况,可以利用前缀函数直接调整B的指针位置,不用回溯A的指针,大大减少比对次数。

Python 代码示例

def compute_prefix_function(B):
    len_B = len(B)
    prefix = [0] * len_B
    j = 0  # 前缀指针
    for i in range(1, len_B):
        # 不匹配时,回溯到上一个匹配的前缀位置
        while j > 0 and B[i] != B[j]:
            j = prefix[j-1]
        # 匹配时,前缀指针前进,记录长度
        if B[i] == B[j]:
            j += 1
            prefix[i] = j
    return prefix

def kmp_find_occurrences(A, B):
    occurrences = []
    len_A, len_B = len(A), len(B)
    
    if len_B == 0 or len_B > len_A:
        return occurrences
    
    prefix = compute_prefix_function(B)
    j = 0  # B的遍历指针
    
    for i in range(len_A):
        # 不匹配时,根据前缀函数调整B的指针
        while j > 0 and A[i] != B[j]:
            j = prefix[j-1]
        # 匹配时,指针前进
        if A[i] == B[j]:
            j += 1
            # 当B的指针走到末尾,说明找到完整匹配
            if j == len_B:
                start_idx = i - len_B + 1
                occurrences.append({
                    "start_index": start_idx,
                    "end_index": i
                })
                # 调整指针,继续查找下一个匹配
                j = prefix[j-1]
    return occurrences

# 测试KMP方法
A = [1, 2, 3, 2, 3, 4, 2, 3]
B = [2, 3]
print(kmp_find_occurrences(A, B))
# 输出和暴力法一致

这个方法的优点是效率极高,适合处理大规模数组;缺点是逻辑相对复杂一点,需要理解前缀函数的作用。


内容的提问来源于stack exchange,提问作者Onur Kuşçuoğlu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:10:16