📌  相关文章
📜  绝对和大于K |的子数组数套装2(1)

📅  最后修改于: 2023-12-03 15:11:40.969000             🧑  作者: Mango

绝对和大于K 的子数组数套装2

简介

在程序设计中,经常需要处理数组中的子数组,而计算子数组的绝对和大于给定数K的个数是一类常见问题。本套装提供了两种解法:暴力枚举和前缀和+二分查找。

暴力枚举解法

暴力枚举的思路很简单:枚举所有的子数组,计算绝对值和是否大于K。时间复杂度为O(n^3)。

代码实现:

int countSubarrays(int[] arr, int k) {
    int n = arr.length;
    int count = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            int sum = 0;
            for (int l = i; l <= j; l++) {
                sum += Math.abs(arr[l]);
            }
            if (sum > k) {
                count++;
            }
        }
    }
    return count;
}
前缀和+二分查找解法

可以使用前缀和来优化暴力枚举,简化绝对得和的计算。具体来说,利用前缀和数组sum[i]表示数组arr前i项的和,则[i,j]子数组的绝对和为sum[j]-sum[i-1],可以转化为绝对值为正数的两个区间和的差值,然后使用二分查找。时间复杂度为O(nlogn)。

代码实现:

int countSubarrays(int[] arr, int k) {
    int n = arr.length;
    int[] sum = new int[n + 1];
    int count = 0;
    for (int i = 1; i <= n; i++) {
        sum[i] = sum[i-1] + arr[i-1];
    }
    for (int i = 0; i < n; i++) {
        int l = i;
        int r = n;
        while (l < r) {
            int mid = (l + r + 1) / 2;
            if (sum[mid] - sum[i] < k) {
                l = mid;
            } else {
                r = mid - 1;
            }
        }
        count += n - l;
    }
    return count;
}
总结

本套装提供了两种解法,暴力枚举和前缀和+二分查找,前者时间复杂度为O(n^3),后者时间复杂度为O(nlogn)。一般情况下,前缀和+二分查找的性能更优。在实际应用中,可以根据数据规模和应用场景选择合适的解法。