• 【LeetCode】和为k的子数组(map统计前缀和)


    和为k的子数组(map统计前缀和)

    题目链接:https://leetcode-cn.com/problems/subarray-sum-equals-k/

    给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。

    示例 1:

    输入:nums = [1,1,1], k = 2
    输出:2
    示例 2:

    输入:nums = [1,2,3], k = 3
    输出:2

    提示:

    1 <= nums.length <= 2 * 104
    -1000 <= nums[i] <= 1000
    -107 <= k <= 107

    题目分析:

    求和为k的子数组数量

    我们从暴力解法一步步推导

    1.首先最基础的暴力是三层循环,两层分别确定区间起始点,最后一层计算此区间和是否为k,时间复杂度为O(N * N * N)

    2.改进一下,简化最后一层循环,用前缀和来计算每次的区间和,时间复杂度:O(N*N)

    3.我们起始不需要知道满足要求的子数组到底是哪些,只要知道到底有多少个符合要求的子数组即可

    • 我们知道每个元素都对应一个前缀和preSum,在遍历数组得到某个元素i的前缀和preSum[i]的时候,如果i之前存在一个历史前缀和,使得当前前缀和减去历史前缀和等于k(即preSum[i]-preSum[j-1]==k),那么此子数组符合要求,计数+1
    • 所以我们只需要在遍历数组时,利用一个map记录下每个元素的前缀和,再每次统计看有没有符合要求的历史前缀和即可
    • 时间复杂度:O(N),空间复杂度:O(N)
    func subarraySum(nums []int, k int) int {
    	preSum:=0 // 前缀和
    	mPreSum:=make(map[int]int) // 统计某一个值的前缀和出现次数
    	mPreSum[0]=1 // 前缀和为0的子数组 出现了一次 ,让下标-1位置对应的前缀和为0
    	count:=0 // 计数器,每次统计符合要求的历史前缀和,即符合要求的子数组数量
    
    	for i:=0;i<len(nums);i++{
    		preSum+=nums[i] // 对每个元素,更新前缀和
    		
    		// 判断此时有没有符合要求的历史前缀和,有则统计
    		if _,ok:=mPreSum[preSum-k];ok{
    			count+=mPreSum[preSum-k]
    		}
    		
    		// 值为preSum的前缀和出现次数+1
    		mPreSum[preSum]++
    	}
    	return count
    }
    
  • 相关阅读:
    第三周作业 1802王兆明
    3.19 第二次作业
    Android-----------ListView练习
    Android----------------------滚动视图练习
    Android-------------------CheckBox小练习
    Android注册
    Android登陆界面
    第一上机练习~~~~~~~~~~~~~~~~~~~~~~~~~~~~武汉一定要加油!!!
    第一上机练习~~~~~~~~~~~~~~~~~~~~~~~~~~~~武汉一定要加油!!!
    第5上机练习~~~~~~~~~~~~~~~~~~~~~~~~~~~~武汉一定要加油!!!
  • 原文地址:https://www.cnblogs.com/yinbiao/p/16122219.html
Copyright © 2020-2023  润新知