前言
這題學習目標是 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
範例
1 2 Input: nums = [1 ,1 ,1 ], k = 2 Output: 2
[1, 1] ⇒ 2 ,符合 k 值的大小 [1, 1] ⇒ 2 ,符合 k 值的大小 所以 nums 陣列可以有兩個子陣列,Output 回傳 2
1 2 Input: nums = [1 ,2 ,3 ], k = 3 Output: 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++
筆者用示意圖可能會比較清晰
1 2 3 4 5 6 7 8 9 10 11 nums = [1 , 1 , 1 , 1 , 2 , 2 , 3 , 5 , 6 , 7 , 8 ] k = 7 prefix_sum = [2 , 2 , 3 ] = 7 prefix_sum_end = [1 , 1 , 1 , 1 , 2 , 2 , 3 ] = 11 prefix_sum_start = [1 , 1 , 1 , 1 ] = 4 prefix_sum_end - sum_prefix_start => [1 , 1 , 1 , 1 , 2 , 2 , 3 ] - [1 , 1 , 1 , 1 ] = 7 prefix_sum = k 成立,count++
JAVA 實現
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Solution { public int subarraySum (int [] nums, int k) { int count = 0 ; int [] sum = new int [nums.length + 1 ]; sum[0 ] = 0 ; for (int i = 1 ; i <= nums.length; i++) sum[i] = sum[i - 1 ] + nums[i - 1 ]; 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 的寫法,不過超過了時間限制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution : def subarraySum (self, nums: List [int ], k: int ) -> int : count = 0 sum = [0 ] * (len (nums)+1 ) sum [0 ] = 0 for i in range (len (nums)+1 ): sum [i] = sum [i-1 ] + nums[i-1 ] 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 的字典來演算,作用是幫助我們統計前綴和出現的次數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution : def subarraySum (self, nums: List [int ], k: int ) -> int : count = 0 prefix_sum = 0 d = {0 : 1 } for num in nums: prefix_sum = prefix_sum + num if prefix_sum - k in d: count = count + d[prefix_sum - k] if prefix_sum not in d: d[prefix_sum] = 1 else : d[prefix_sum] = d[prefix_sum] + 1 return count
成績
Language
Runtime
Memory
Java
1556ms
44.65MB
Python
264ms
18.91MB