[LeetCode] 923. 3Sum With Multiplicity
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:
Input: arr = [1,1,2,2,3,3,4,4,5,5], target = 8
Output: 20
Explanation:
Enumerating by the values (arr[i], arr[j], arr[k]):
(1, 2, 5) occurs 8 times;
(1, 3, 4) occurs 8 times;
(2, 2, 4) occurs 2 times;
(2, 3, 3) occurs 2 times.
Example 2:
Input: arr = [1,1,2,2,2,2], target = 5
Output: 12
Explanation:
arr[i] = 1, arr[j] = arr[k] = 2 occurs 12 times:
We choose one 1 from [1,1] in 2 ways,
and two 2s from [2,2,2,2] in 6 ways.
Example 3:
Input: arr = [2,1,3], target = 6
Output: 1
Explanation: (1, 2, 3) occured one time in the array so we return 1.
Constraints:
3 <= arr.length <= 3000
0 <= arr[i] <= 100
0 <= target <= 300
多重三数之和。
给定一个整数数组 arr ,以及一个整数 target 作为目标值,返回满足 i < j < k 且 arr[i] + arr[j] + arr[k] == target 的元组 i, j, k 的数量。由于结果会非常大,请返回 109 + 7 的模。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/3sum-with-multiplicity
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
这道题我们找的是一个满足题意的三元组,但是注意因为 input 里面给的数字是有重复的,所以计算的时候要小心一些。因为题目要求三个数的下标要满足 i < j < k,这道题的做法是类似 two sum 的思路,也是先固定前两个数字,然后在剩下的数字中寻找第三个数字。不同的是,这道题的 input 数组里面有重复的数字,所以我们需要记录每个数字出现的次数。
首先我们记录一下 input 数组里面每个数字都分别出现的次数,用一个 count 数组记录好。接着我们还是按 3sum 的思路开始遍历,首先确定前两个数字 i, j(注意这里的 i, j, k 其实不是下标,题目说的不清楚,这里其实指的是三数之和里三个不同的数字),那么要找的第三个数字 k = target - i - j。如果 k 的范围不在 0 - 100 则说明是一个无效的组合(因为题目的数据范围规定 0 <= arr[i] <= 100),直接跳过即可;当 k 是一个有效的数字的时候,也需要判断如下几种 case
- 如果 i == j && j == k,说明 i, j, k 三个数字相同。对于三个数字相同的组合,他们可以产生的组合数量是 count[i] * (count[i] - 1) * (count[i] - 2) / 6
- 如果 i == j && j != k, 说明其中两个数字相同,组合数量是 count[i] * (count[i] - 1) / 2 * count[k]
- 如果三个数字都互不相同,组合数量是 count[i] * count[j] * count[k]
这个做法巧妙之处在于他扫描的不是原数组,而是根据题目给的数据范围去扫描(0 - 100)。比如第一个例子的 target = 8,input数组里有 1 和 2,假设此时没有 5 的话,根据我们的算法,count[5] == 0,所以 1 + 2 + 5 = 8 这个组合也不会找的到。
复杂度
时间O(n^2)
空间O(n)
代码
Java实现
1 |
|