使用C++编写,找到和小于K的子数组的数量

使用C++编写,找到和小于K的子数组的数量

在计算机科学中,数组是一种数据类型,用于存储一系列相同类型的元素。子数组是指连续的一段元素组成的数组。找到和小于给定值K的子数组数量是一个常见的问题,我们可以通过编写C++代码来解决此问题。

算法解析

暴力算法

一个最简单的思路是使用两个循环。最外层循环从0到n-1遍历数组,内层循环从1到n依次计算子数组的和并比较,记录小于K的子数组的数量。这个算法的时间复杂度为O(n^2)。

int countSubarray(int arr[], int n, int k) {

int count = 0;

for (int i = 0; i < n; i++) {

int sum = arr[i];

if (sum < k) {

count++;

}

for (int j = i + 1; j < n; j++) {

sum += arr[j];

if (sum < k) {

count++;

}

}

}

return count;

}

但是,这个算法的时间复杂度较高。如果数组很大,计算的时间也会很长。

前缀和算法

前缀和是指一个数列中前n项的和。我们可以使用前缀和来优化我们的算法。我们可以用一个新的数组pre_sum[] 记录从0到i的元素的和。因此, A[i…j] 的和可以表示为 pre_sum[j]–pre_sum[i-1]。 我们可以通过将pre_sum数组排序并查找第一个大于或等于pre_sum[j] - K的位置p ,然后计算p到j的子数组的数量。

int countSubarray(int arr[], int n, int k) {

int count = 0;

int pre_sum[n];

pre_sum[0] = arr[0];

for (int i = 1; i < n; i++) {

pre_sum[i] = pre_sum[i - 1] + arr[i];

}

sort(pre_sum, pre_sum + n);

for (int i = 0; i < n; i++) {

int j = upper_bound(pre_sum, pre_sum + n, k + (i > 0 ? pre_sum[i - 1] : 0)) - pre_sum;

count += j - i - 1;

}

return count;

}

这个算法的时间复杂度为O(nlogn)。我们可以将算法的性能进一步优化。我们可以使用一个map来存储pre_sum数组中的值。

使用Map优化后缀和算法

我们可以使用一个map来存储pre_sum数组中的值。我们初始化map为一个值为1的元素,这是因为在pre_sum集合中第一个元素也应该被考虑进去。然后我们遍历pre_sum数组中的元素,将map中有前缀和-elements[i]或小于其的元素的次数加入答案。

int countSubarray(int arr[], int n, int k) {

unordered_map mp;

int pre_sum = 0;

mp[0] = 1;

int count = 0;

for (int i = 0; i < n; i++) {

pre_sum += arr[i];

count += mp[pre_sum - k];

mp[pre_sum]++;

}

return count;

}

这个算法的时间复杂度为O(n)。

总结

通过使用前缀和和map,我们可以得到比暴力算法更快的算法。前缀和用于快速计算一个子数组中的元素之和。而使用map则可以保存前缀和中的元素(减去给定值k)出现的次数,从而在O(1)的时间内找到答案。因此,我们可以在O(nlogn)或O(n)的时间内找到和小于给定值k的子数组的数量。

免责声明:本文来自互联网,本站所有信息(包括但不限于文字、视频、音频、数据及图表),不保证该信息的准确性、真实性、完整性、有效性、及时性、原创性等,版权归属于原作者,如无意侵犯媒体或个人知识产权,请来电或致函告之,本站将在第一时间处理。猿码集站发布此文目的在于促进信息交流,此文观点与本站立场无关,不承担任何责任。

后端开发标签