Problem
Given an integer array arr
, and an integer target
, return the number of tuples i, j, k
such that i < j < k
and arr[i] + arr[j] + arr[k] == target
.
As the answer can be very large, return it modulo 109 + 7
.
Example 1:
1 | Input: arr = [1,1,2,2,3,3,4,4,5,5], target = 8 |
Example 2:
1 | Input: arr = [1,1,2,2,2,2], target = 5 |
Constraints:
3 <= arr.length <= 3000
0 <= arr[i] <= 100
0 <= target <= 300
Analysis
题目是3 sum的改进版,最原始的3 sum的数组中的数字是唯一的,而这里数组中的数字是不唯一的,题目要求找出能够构成目标值的三个数字的组合的数量。所以这道题目可以分成两个部分,第一个是找出三个数加起来为目标值,第二个是把组合的数量计算出来。
第一部分好做,就是3 sum的做法。先确定一个数组,然后有左右两个下标来找出剩下的两个数,这个比较简单,这里不再赘述。
难的是第二部分,如何求出满足条件的组合数量。如果不存在重复的数字,那么找到的满足题目条件的三元组数量就是答案的数量。这里要解决的是重复数字的问题,其实也并不难。因为我们在处理第一部分的时候,已经把数组排好序,所以重复的数字是相邻出现的,因此在找到剩下的两个数字后(分别是arr[j]
和arr[k]
),我们找与这两个数字相同的数分别有多少个。j
往右找,假设找到了left
个;k
往左找,假设找到了right
个。这样就知道每个数字各有多少个,相互组合即可。
Solution
这里有个点需要注意,找到重复数组组合时,要分情况处理:
- 当
arr[j] != arr[k]
时,组合数量就是$left \times right$; - 当
arr[j] == arr[k]
时,说明这两个数字是一样的,所以k - j
就是这个数字出现的数量,而计算组合时,我们需要从中抽取两个出来,利用组合数公式,此时组合的数量就是$\frac{(k - j + 1) \times (k - j)}{2}$。
Code
1 | class Solution { |
Summary
这道题目是属于3sum的一个变种,找三元组的方法是一样的,增加的难点在于如何处理重复数字带来的组合问题。同时还要特别注意相同数组的组合计算问题。这道题目的分享到这里,感谢你的支持!