查找总和等于给定值的子数组的数量

时间:2019-09-16 20:45:24

标签: java algorithm

我试图了解一个程序,任务是查找可能有多少个子数组,其总和等于给定值。

以下是从link提取的具有O(N)复杂度的工作代码:

static int findSubarraySum(int arr[], int K) {
    Map<Integer, Integer> prevSum = new HashMap<>();
    int res = 0;
    int currsum = 0;
    for (int i = 0; i < arr.length; i++) {
        currsum += arr[i];
        if (currsum == K)
            res++;
        if (prevSum.containsKey(currsum - K))
            res += prevSum.get(currsum - K);
        Integer count = prevSum.get(currsum);
        if (count == null)
            prevSum.put(currsum, 1);
        else
            prevSum.put(currsum, count + 1);
    }

    return res;
}

public static void main(String[] args) {
    int arr[] = {10, 2, -2, -20, 10};
    int sum = -10;
    int n = arr.length;
    System.out.println(findSubarraySum(arr, sum));
}

我无法理解下面代码的逻辑:

            if (prevSum.containsKey(currsum - K))   
                res += prevSum.get(currsum - K);  

以上代码中的HashMap如何有助于获得正确的结果。

1 个答案:

答案 0 :(得分:1)

prevSum[i]包含从第一个元素开始的,总计为i的连续子数组的数量。例如,对于数组3, 4, 2, -4, 2,条目将如下所示:

prevSum[3] = 1  // { { 3 } }
prevSum[5] = 1  // { { 3, 4, 2, -4 } }
prevSum[7] = 2  // { { 3, 4 }, { 3, 4, 2, -4, 2} }
prevSum[9] = 1  // { { 3, 4, 2 } }

如果当前前缀总和currsum10,并且正在寻找总和为K=3的子数组,则要删除以第一个元素开头并求和为7以获取总计为3的适当子数组。示例:

3, 4, 2, -4, 2, 1, 2, -5, 2
                   ^
|------------------|
              currsum = 10

|--|  -> sums to 7
     |-------------| -> sums to 3

|------------| -> sums to 7
                |--| -> sums to 3

因此,在此位置,您找到了两个总计为K的可能子数组。因此,res += prevSum.get(currsum - K)