2026-03-19:边界与内部和相等的稳定子数组。用go语言,给定一个整数数组 capacity,请统计其中有多少个连续区间符合下面的要求: - 区间内至少包

0 阅读5分钟

2026-03-19:边界与内部和相等的稳定子数组。用go语言,给定一个整数数组 capacity,请统计其中有多少个连续区间符合下面的要求:

  • 区间内至少包含 3 个元素;

  • 这个区间的第一个数和最后一个数相同;

  • 并且这两个端点的值,恰好等于它们中间所有元素的总和。

换句话说,如果某个子数组的左右两端相等,而且这个相等的值正好能被中间部分全部加起来得到,那么这个子数组就算作一个“稳定”子数组。

你的任务是:返回这样的子数组总数。

3 <= capacity.length <= 100000。

-1000000000 <= capacity[i] <= 1000000000。

输入: capacity = [9,3,3,3,9]。

输出: 2。

解释:

[9,3,3,3,9] 是稳定数组,因为首尾元素都是 9,且它们之间元素之和为 3 + 3 + 3 = 9。

[3,3,3] 是稳定数组,因为首尾元素都是 3,且它们之间元素之和为 3。

题目来自力扣3728。

一、算法整体大体过程(分步骤详细描述)

步骤1:定义核心工具

  1. 前缀和数组prefix[i] 表示数组前i个元素的累加和(快速计算任意区间和);
  2. 哈希表(字典):存储键值对,键是二元组 (当前元素值, 前缀和值),值是该二元组出现的次数; 作用:快速查找满足条件的左端点L,避免暴力遍历所有子数组。

步骤2:初始化变量

  1. 初始化答案计数器:用于统计符合条件的稳定子数组数量(初始为0);
  2. 初始化前缀和:从数组第一个元素开始计算;
  3. 初始化哈希表:为空,后续动态存入二元组。

步骤3:遍历数组(右指针遍历,从第二个元素开始)

以右指针r代表子数组的右端点,逐个遍历数组元素,核心逻辑分3步:

  1. 查询匹配的左端点 以当前右端点值capacity[r]、当前前缀和为条件,去哈希表中查找: 有没有左端点L 满足:

    • capacity[L] = capacity[r](首尾相等);
    • prefix[L] + capacity[L] = 前缀和(中间和等于端点值)。 查到的次数,直接累加到答案计数器中(每一次匹配都对应一个稳定子数组)。
  2. 存入新的二元组到哈希表左候选点(当前右指针的前一个元素)的二元组: (capacity[r-1], prefix[r-1] + capacity[r-1]) 存入哈希表,计数+1(为后续的右端点提供匹配依据)。

  3. 更新前缀和 把当前元素的值加到前缀和中,继续下一轮遍历。

步骤4:遍历结束,返回答案

遍历完成后,答案计数器的值就是所有符合条件的稳定子数组数量。


二、示例推演(输入 [9,3,3,3,9]

数组索引:0(9)、1(3)、2(3)、3(3)、4(9) 目标结果:2个稳定子数组 [0,4][1,3]

  1. 初始:前缀和=9(索引0),哈希表空,答案=0;
  2. r=1(元素3):查询无匹配,存入(9, 9+9=18),前缀和更新为12;
  3. r=2(元素3):查询无匹配,存入(3, 3+12=15),前缀和更新为15;
  4. r=3(元素3):查询哈希表,匹配到(3,15),答案+1(对应子数组[1,3]),存入(3,3+15=18),前缀和更新为18;
  5. r=4(元素9):查询哈希表,匹配到(9,18),答案+1(对应子数组[0,4]),存入新二元组,前缀和更新为27; 最终答案=2,与预期一致。

三、时间复杂度 & 额外空间复杂度

1. 时间复杂度

  • 算法仅一次遍历数组,遍历次数为数组长度n
  • 哈希表的查询、插入操作都是平均 O(1) 时间;
  • 总时间复杂度:O(n)
  • 适配题目要求:数组长度最高10⁵,O(n)算法可高效运行。

2. 额外空间复杂度

  • 仅使用了一个哈希表存储二元组;
  • 哈希表最多存储n个键值对(遍历中每个元素最多存入一次);
  • 无其他大规模数据结构;
  • 总额外空间复杂度:O(n)

总结

  1. 算法核心:前缀和+哈希表,将暴力O(n²)优化为O(n);
  2. 过程:右指针遍历→哈希表查匹配左端点→更新答案→存入新候选→更新前缀和;
  3. 复杂度:时间O(n),空间O(n),完美适配大数据量的题目要求。

Go完整代码如下:

package main

import (
	"fmt"
)

func countStableSubarrays(capacity []int) (ans int64) {
	type pair struct{ x, s int }
	cnt := map[pair]int{}
	sum := capacity[0] // 前缀和
	for r := 1; r < len(capacity); r++ {
		ans += int64(cnt[pair{capacity[r], sum}])
		cnt[pair{capacity[r-1], capacity[r-1] + sum}]++
		sum += capacity[r]
	}
	return
}

func main() {
	capacity := []int{9, 3, 3, 3, 9}
	result := countStableSubarrays(capacity)
	fmt.Println(result)
}

在这里插入图片描述

Python完整代码如下:

# -*-coding:utf-8-*-

from typing import List
from collections import defaultdict

def count_stable_subarrays(capacity: List[int]) -> int:
    """
    计算稳定子数组的数量
    
    参数:
        capacity: 整数列表
        
    返回:
        稳定子数组的数量
    """
    ans = 0
    # 使用字典来存储pair计数,Python中的元组可以直接作为字典键
    cnt = defaultdict(int)
    
    # 前缀和
    prefix_sum = capacity[0]
    
    # 从索引1开始遍历
    for r in range(1, len(capacity)):
        # 查询并累加符合条件的子数组数量
        ans += cnt[(capacity[r], prefix_sum)]
        
        # 更新计数
        cnt[(capacity[r-1], capacity[r-1] + prefix_sum)] += 1
        
        # 更新前缀和
        prefix_sum += capacity[r]
    
    return ans

def main():
    # 测试用例
    capacity = [9, 3, 3, 3, 9]
    result = count_stable_subarrays(capacity)
    print(result)

if __name__ == "__main__":
    main()

在这里插入图片描述

C++完整代码如下:

#include <iostream>
#include <vector>
#include <map>
#include <tuple>

using namespace std;

// 定义pair结构体,用于作为map的键
struct Pair {
    int x;  // 元素值
    int s;  // 和/前缀和

    // 需要定义比较运算符才能作为map的键
    bool operator<(const Pair& other) const {
        if (x != other.x) return x < other.x;
        return s < other.s;
    }
};

long long countStableSubarrays(vector<int>& capacity) {
    long long ans = 0;
    map<Pair, int> cnt;  // 使用map代替Go的map

    int sum = capacity[0];  // 前缀和

    for (int r = 1; r < capacity.size(); r++) {
        // 查询并累加符合条件的子数组数量
        ans += cnt[{capacity[r], sum}];

        // 更新计数
        cnt[{capacity[r-1], capacity[r-1] + sum}]++;

        // 更新前缀和
        sum += capacity[r];
    }

    return ans;
}

int main() {
    // 测试用例
    vector<int> capacity = {9, 3, 3, 3, 9};
    long long result = countStableSubarrays(capacity);
    cout << result << endl;

    return 0;
}

在这里插入图片描述