From da753b2b035ab282df6948bf2da1d5fd81bbbf95 Mon Sep 17 00:00:00 2001 From: Sangeeth Sudheer Date: Thu, 7 Apr 2022 02:19:51 +0530 Subject: [PATCH] feat(0959_3sum-with-multiplicity): add py3 soln --- 0959_3sum-with-multiplicity/README.md | 31 ++++++++ .../python3/solution.py | 0 .../python3/three-pointer.py | 70 +++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 0959_3sum-with-multiplicity/README.md create mode 100644 0959_3sum-with-multiplicity/python3/solution.py create mode 100644 0959_3sum-with-multiplicity/python3/three-pointer.py diff --git a/0959_3sum-with-multiplicity/README.md b/0959_3sum-with-multiplicity/README.md new file mode 100644 index 0000000..d8bf5bf --- /dev/null +++ b/0959_3sum-with-multiplicity/README.md @@ -0,0 +1,31 @@ +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. + + +**Constraints:** + +* `3 <= arr.length <= 3000` +* `0 <= arr[i] <= 100` +* `0 <= target <= 300` \ No newline at end of file diff --git a/0959_3sum-with-multiplicity/python3/solution.py b/0959_3sum-with-multiplicity/python3/solution.py new file mode 100644 index 0000000..e69de29 diff --git a/0959_3sum-with-multiplicity/python3/three-pointer.py b/0959_3sum-with-multiplicity/python3/three-pointer.py new file mode 100644 index 0000000..b4efee9 --- /dev/null +++ b/0959_3sum-with-multiplicity/python3/three-pointer.py @@ -0,0 +1,70 @@ +# Time: O(N^2) +# Space: O(1) +# NOTE: i, j, k mentioned in the problem refers to indices, not +# the values in the array! So, duplicates are A-OK! + +class Solution: + def threeSumMulti(self, arr: List[int], target: int) -> int: + # To use 2-pointer technique + arr.sort() + + n = len(arr) + result = 0 + + for i, _ in enumerate(arr): + diff = target - arr[i] + j, k = i + 1, n - 1 + + while j < k: + # Inside this, it's pretty much two-sum and + # we use the two pointers to move from left + # and right if they don't equal `diff` + if arr[j] + arr[k] < diff: + j += 1 + + elif arr[j] + arr[k] > diff: + k -= 1 + + # Following condition but we know arr[j] + arr[k] == diff + elif arr[j] != arr[k]: + # Count all of arr[j] and arr[k] instances + count_j = count_k = 1 + + while j + 1 < k and arr[j + 1] == arr[j]: + count_j += 1 + j += 1 + + while k - 1 > j and arr[k - 1] == arr[k]: + count_k += 1 + k -= 1 + + result += count_j * count_k + + j += 1 + k -= 1 + + else: + # If both are equal, then we have a range similar to the following: + # + # [4, 4, 4, 4] + # ^ ^ + # | | + # j k + # + # So, they are the same! We have (k - j + 1) elements to pick from and + # we can use combination to solve this cause we shouldn't consider (3i, 4i) + # and (4i, 3i) to be the same + num_dups = k - j + 1 + + # num_dups num_dups! + # C = ---------------------- + # 2 2! ยท (num_dups - 2)! + # + # = (num_dups * (num_dups - 1)) / 2 + + result += (num_dups * (num_dups - 1)) // 2 + + # Since it's all duplicates from j to k, we break + break + + return result % (10 ** 9 + 7)