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”


猜你喜欢

转载自blog.csdn.net/laioffer/article/details/80202129