leetcode-560 <Subarray Sum Equals K>

题目:
Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.
A subarray is a contiguous non-empty sequence of elements within an array.

Example 1:
Input: nums = [1,1,1], k = 2
Output: 2

Example 2:
Input: nums = [1,2,3], k = 3
Output: 2

题目分析:连续子数组的和等于k一共有几种情况
思路分析:

1、最简单的方法就是暴力循环,通过两个for循环来相加判断。时间复杂度为n的平方。计算机每秒可以进行数千万到数亿( 10的8次方数量级)的运算,如果超过这个时间,则视为超时。

由于这道题的数组长度区间为1 <= nums.length <= 2 * 10的4次方,明显用n方会超时。不考虑。

2、用空间来换取时间,来达到On的时间复杂度。
首先On的时间复杂度一定是只对数组遍历了一次,在遍历一次的情况下如何灵活的求连续子区间的和?

在计算数组i-j之间的和时,能想到的有两种方法:

  1. 从i顺序加到j,这个过程又包含了一次遍历
  2. 使用sum[j] - sum[i - 1]来得到i-j的和

方法1不考虑,因为时间复杂度不满足On。
方法2里,通过sum[j] - sum[i - 1] 计算得到i-j的和,如果 k === i-j,此时Output+1. 根据方法2的思路,我们可以把当前坐标的和存储在Map表里,如果sum[j] - k的值存在于Map表里,则说明sum[j] - sum[i - 1] === k成立,此时存在一个连续子区间的和等于k。

利用方法2,我们可以得到的解题代码如下:

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var subarraySum = function(nums, k) {
    var result = 0
    var map = new Map()
    map.set(0,1)
    var presum = 0
    
    for(let i = 0; i < nums.length; i++) {
        presum = presum + nums[i]
        //  sum[j] - sum[i - 1] === k成立,结果加1
        if(map.get(presum - k)) {
            result = result + map.get(presum - k)
        }
        // 不存在当前坐标和时,存储在Map里
        if(!(map.get(presum))) {
            map.set(presum, 1)
        } else {
            // 如果已经存在于Map表里,说明之前已经有一个连续子区间的
            map.set(presum, map.get(presum) + 1)
        }
    }
    return result
};
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容