[LeetCode 笔记] 560. Subarray Sum Equals K

前言

  这题学习目标是 Prefix Sums 前缀和的概念, Prefix Sums 通常用于需要频繁查询阵列中某一区间的元素和的情况,这里目标是找到一个阵列中连续子阵列的合回传最大值,时间複杂度估为 O(n^2),这里有 JAVA 和 Python 的写法。

题目

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.

给定一个整数阵列 nums 和一个整数 k,回传总合等于 k 值的连续子阵列的数量。
子阵列是阵列中连续的非空元素阵列。

题目连结:https://leetcode.com/problems/subarray-sum-equals-k/

题目限制

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

範例

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

[1, 1] ⇒ 2 ,符合 k 值的大小
[1, 1] ⇒ 2 ,符合 k 值的大小
所以 nums 阵列可以有两个子阵列,Output 回传 2

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

[1, 2] ⇒ 3 ,符合 k 值的大小
[3] ⇒ 3 ,符合 k 值的大小
所以 nums 阵列可以有两个子阵列,Output 回传 2

思路&笔记

这题主要的思路是 Prefix Sums 为某一个区间和的算法

我们先把符合 nums 阵列其中一个连续子阵列,拿出来做说明回推假如有一连续子阵列 prefix_sum = [2, 2, 3]然后把这个子阵列的前缀和的终点 - 前缀和的起点,终点就是 3 ,起点就是 2这里概念上不是数学上的减去,而是空间上的减去如果获取的子阵列 prefix_sum 的前缀和相减等于 k 的话 count++

笔者用示意图可能会比较清晰

// for examplenums = [1, 1, 1, 1, 2, 2, 3, 5, 6, 7, 8]k = 7prefix_sum = [2, 2, 3] = 7prefix_sum_end = [1, 1, 1, 1, 2, 2, 3] = 11prefix_sum_start = [1, 1, 1, 1] = 4prefix_sum_end - sum_prefix_start => [1, 1, 1, 1, 2, 2, 3] - [1, 1, 1, 1] = 7prefix_sum = k 成立,count++

JAVA 实现

public class Solution {    public int subarraySum(int[] nums, int k) {        int count = 0;        int[] sum = new int[nums.length + 1]; // 设定前缀和的阵列        sum[0] = 0; // 设定阵列第一个索引为 0        // 把阵列中所有的元素加起来,组合成各个前缀和        for (int i = 1; i <= nums.length; i++)            sum[i] = sum[i - 1] + nums[i - 1]; // sum = [0, 1, 1+2, 1+2+3]              for (int start = 0; start < sum.length; start++) {            for (int end = start + 1; end < sum.length; end++) {                if (sum[end] - sum[start] == k) // 前缀和的终点 - 前缀和的起点                    count++;            }        }              return count;    }}

Python 实现

使用了和 Java 一样的逻辑执行,换成 Python 的写法,不过超过了时间限制

class Solution:    def subarraySum(self, nums: List[int], k: int) -> int:        count = 0        sum = [0] * (len(nums)+1) # 设定前缀和的阵列        sum[0] = 0 # 设定阵列第一个索引为 0        # 把阵列中所有的元素加起来,组合成各个前缀和        for i in range(len(nums)+1):            sum[i] = sum[i-1] + nums[i-1] # sum = [0, 1, 1+2, 1+2+3]        for start in range(len(sum)):            for end in range(start+1, len(sum)):                if sum[end] - sum[start] == k: # 前缀和的终点 - 前缀和的起点                    count+=1        return count

另一种写法加入 python 的字典来演算,作用是帮助我们统计前缀和出现的次数

class Solution:    def subarraySum(self, nums: List[int], k: int) -> int:        count = 0         prefix_sum = 0 # 当前的前缀和        # 字典 d 的 key 是前缀和,value 是该前缀和出现的次数        d = {0 : 1} # 初始将 0 的出现次数设为 1,表示前缀和为 0 的情况        for num in nums:            prefix_sum = prefix_sum + num # 更新当前的前缀和            # 因为已经设定为 0 ,说明存在一个前缀和相减为 0 ,代表和 k 一样            if prefix_sum - k in d:                count = count + d[prefix_sum - k] # count 次数:0 + 1            # 如果不存在,表示这是首次遇到这个前缀和,将该前缀和作为 key,将其出现次数设为 1。            if prefix_sum not in d:                d[prefix_sum] = 1            else:                d[prefix_sum] = d[prefix_sum] + 1 # 代表已经有其他前缀和等于当前的前缀和,把相同的前缀和 + 1        return count

成绩

LanguageRuntimeMemoryJava1556ms44.65MBPython264ms18.91MB(新手上路,如有错误请友善告知,感谢)

Blog
https://chris81051.github.io/2023/10/09/LeetCode-560-Subarray-Sum-Equals-K-Java-Python/
有分享技术文章、科技新闻、日常生活,欢迎一起讨论


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章