Google, Facebook高频面试题 | Subarray Sum Equals K
先一起来看看题目:
题目描述
Given an array of integers and an integer k, you need to find the total number of contiguous subarrays whose sum equals to k.
Example 1:
Input: nums = [1,1,1], k = 2Output: 2
[1, 1, 1]
[1, 1, 1]
考点解析
在面试中我们经常会碰到一类问题,跟input array中的所有subarray sum相关。
在这类题目中,我们可以使用到一个非常常见的precomputation的方法来进行优化:prefixSum array。
今天的习题讲解,我们就重点讲解一下:
如何利用prefixSum array的思想,非常有效的解决Subarray Sum Equals K这个问题。
接下来,我们有请闫老师为我们详解这道题的答案:
主讲人:闫老师
来Offer金牌老师
前Google资深程序员、面试官
Google连续多年top performer
解题思路
在这道题目中,闫老师讲解了三个不同的解法,从最naive的解法,到optimize的解法。并一步步讲解本题的优化过程。
解法1:Naive Solution
拿到题目,我们很快就能想到的一个最直接的方法:
找到input array的所有可能的subarray,然后判断每个subarray的和是否与k相等。
一个比较暴力的方法,就是用三层for loop,找到所有可能的subarray,并遍历subarray中的每个数,计算subarray的和。
解法2:Better Solution
从上一个解法出发,我们能看到一个比较明显的优化就是减少重复计算。
在Naive的解法中,在计算subarray的和的时候,我们每次都需要遍历该subarray中的每个数。实际上,这是有很多重复的。
以subarray(i, j)为例(i为subarray的起点,j为终点):
当i = 0,j = 1的时候,需要遍历nums[0], nums[1]。
当i = 0, j = 2的时候,需要遍历nums[0], nums[1], nums[2]。
显然,前两个数字被遍历了多次。图中蓝色部分为重复遍历的元素。
那么,减少重复的一个方法,就是把之前已经计算过的subarray(i, j)的和保存下来,当j++的时候我们只需要在原来的和的基础上加上新的nums[j],来达到减少重复遍历的目的,也降低了时间复杂度。
解法3:Linear Solution
进一步优化,我们会用到一个非常重要的precomputation的技巧:prefixSum array。
prefixSum array的每一个index所对应的value,和最开始的input array有一个对应关系:
通过这个prefixSum array,我们就可以用O(1)的时间求出任意一个subarray的和:
sum of subarray(i, j) = prefixSum[j] - prefixSum[i - 1]
注意上图中红色的0,是为了解决当i == 0的时候的subarray(i, j)的和,这时对应的prefixSum[i - 1]应该是0
有了prefixSum array,这个问题就转化成了
for each j:how many i < j satisfies prefixSum[i] = prefixSum[j] - k
这意味着对于每个j,我们需要记录之前所有的prefixSum,然后在这些prefixSum中查找有多少个数值 == prefixSum[j] - k。
这是一个look up的操作,为了更加有效的解决这个问题,我们可以使用一个HashMap:
key:prefixSum value
value:number of occurence of the prefixSum value。
在实际实现中,我们发现,在从左到右遍历整个array过程中,我们可以只需要一个prefixSum的variable来依次计算所有的prefixSum值,并将其存入HashMap中,无需提前计算出整个prefixSum array。
代码实现
算法与代码中需要注意的细节处理及时间、空间复杂度分析请观看视频讲解。
E/N/D
更多科技求职资讯,请关注“来Offer”