蓝桥杯 云神的子数组和

原题目链接

题意

给定长度为n的整数数组,统计和等于x的连续子数组数量。

超时写法:暴力枚举(双重循环)

思路

枚举每个子数组的起点 (i),再从 (i) 向右枚举终点 (j),维护从 (i) 到 (j) 的累加和 sum

  • 每次 sum += arr[j]
  • sum == x,则答案 ans++

这样能统计所有连续子数组,但当 (n) 很大时会超时。

复杂度

  • 时间复杂度: O ( n 2 ) O(n^{2}) O(n2)

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

int n, x, s = 0, e = 0, ans = 0;
int arr[100005];

int main() {
    cin >> n >> x;
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
    }
    for (int i = 0; i < n; i++) {
    int sum = 0;
        for (int j = i; j < n; j++) {
            sum += arr[j];
            if (sum == x) ans++;
        }
    }
    cout << ans;
    return 0;
}//by wqs

前缀和 + Hash 优化

思路

用前缀和思想:设当前前缀和为 sum,如果存在某个以前出现过的前缀和为 sum - x,那么从那个位置之后到当前位置的子数组和就是 (x)。

做法是用 unordered_map 统计每个前缀和出现次数:

  • 初始化 prefix_sum_unordered_map[0] = 1(表示空前缀)
  • 每读入一个数更新 sum
  • target = sum - x
  • prefix_sum_unordered_map[target] 加到答案上
  • 再把当前 sum 的计数加 1

复杂度

  • 平均时间复杂度: O ( n ) O(n) O(n)

代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

int n, x, s = 0, e = 0, sum = 0, ans = 0;
int arr[100005];
unordered_map<int, int> prefix_sum_unordered_map;

int main() {
	cin >> n >> x;
	prefix_sum_unordered_map[0] = 1;
	for (int i = 0; i < n; i++) {
		cin >> arr[i];
		sum += arr[i];
		int target = sum - x;
		ans += prefix_sum_unordered_map[target];
		prefix_sum_unordered_map[sum]++;
	}
	cout << ans;
	return 0;
}//by wqs。
相关推荐
灵感__idea1 小时前
Hello 算法:贪心的世界
前端·javascript·算法
澈2072 小时前
深入浅出C++滑动窗口算法:原理、实现与实战应用详解
数据结构·c++·算法
ambition202422 小时前
从暴力搜索到理论最优:一道任务调度问题的完整算法演进历程
c语言·数据结构·c++·算法·贪心算法·深度优先
cmpxr_2 小时前
【C】原码和补码以及环形坐标取模算法
c语言·开发语言·算法
qiqsevenqiqiqiqi3 小时前
前缀和差分
算法·图论
代码旅人ing3 小时前
链表算法刷题指南
数据结构·算法·链表
Yungoal3 小时前
常见 时间复杂度计算
c++·算法
不爱吃炸鸡柳4 小时前
单链表专题(完整代码版)
数据结构·算法·链表
CylMK4 小时前
题解:AT_abc382_d [ABC382D] Keep Distance
算法
Dfreedom.4 小时前
计算机视觉全景图
人工智能·算法·计算机视觉·图像算法