Count Good Triplets in an Array - Complete Solution Guide
Count Good Triplets in an Array is LeetCode problem 2179, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
You are given two 0-indexed arrays nums1 and nums2 of length n , both of which are permutations of [0, 1, ..., n - 1] . A good triplet is a set of 3 distinct values which are present in increasing order by position both in nums1 and nums2 . In other words, if we consider pos1 v as the index of the value v in nums1 and pos2 v as the index of the value v in nums2 , then a good triplet will be a set (x, y, z) where 0 <= x, y, z <= n - 1 , such that pos1 x < pos1 y < pos1 z and pos2 x < pos2 y < pos
Detailed Explanation
The problem asks us to find the number of "good triplets" in two arrays, `nums1` and `nums2`, which are permutations of the numbers from 0 to n-1. A good triplet (x, y, z) satisfies two conditions: 1) x, y, and z are distinct values within the range [0, n-1], 2) The indices of x, y, and z are in increasing order in both `nums1` and `nums2`. In other words, if `pos1[v]` is the index of value `v` in `nums1`, and `pos2[v]` is the index of value `v` in `nums2`, then a good triplet (x, y, z) must satisfy `pos1[x] < pos1[y] < pos1[z]` and `pos2[x] < pos2[y] < pos2[z]`.
Solution Approach
The solution uses a Binary Indexed Tree (BIT), also known as a Fenwick Tree, to efficiently count the number of elements smaller than a given value in a range. First, the positions of each number in `nums2` are stored in an array `pos2`. Then, a new array `A` is created, where `A[i]` stores the position of `nums1[i]` in `nums2`. Now, the problem is reduced to finding triplets (i, j, k) such that i < j < k and A[i] < A[j] < A[k]. The code iterates through the array `A` and for each element `A[j]`, it counts the number of elements `A[i]` to the left of `j` that are less than `A[j]` and the number of elements `A[k]` to the right of `j` that are greater than `A[j]`. The product of these two counts gives the number of good triplets with 'j' as the middle element. The sum of these products over all possible values of 'j' is the total number of good triplets.
Step-by-Step Algorithm
- Step 1: Create an array `pos2` to store the positions of each element in `nums2`. `pos2[i]` will store the index of the element `i` in `nums2`.
- Step 2: Create an array `A` where `A[i] = pos2[nums1[i]]`. This transforms the problem into finding triplets `i < j < k` such that `A[i] < A[j] < A[k]`.
- Step 3: Initialize two Binary Indexed Trees (BITs), `left_bit` and `right_bit`. `left_bit` will store the count of elements seen so far from the left, and `right_bit` will store the count of elements to the right.
- Step 4: Initially, populate the `right_bit` with all elements from array `A`. This is done because at the start, all elements are to the right of the current middle element we're considering.
- Step 5: Iterate through the array `A`. In each iteration (for the current middle element `A[i]`):
- Step 6: Remove the element `A[i]` from `right_bit` since it is no longer to the right.
- Step 7: Query `left_bit` to find the number of elements to the left of `i` that are less than `A[i]`. This is `less_on_left`.
- Step 8: Query `right_bit` to find the number of elements to the right of `i` that are greater than `A[i]`. This is done by subtracting the number of elements less than or equal to `A[i]` from the total number of elements present in `right_bit`.
- Step 9: Update the `ans` with `less_on_left * greater_on_right`.
- Step 10: Add the element `A[i]` to `left_bit`.
- Step 11: After iterating through all elements, return the `ans`.
Key Insights
- Insight 1: Precompute the positions of each number in `nums2` to make it easier to check the second condition (increasing order in `nums2`).
- Insight 2: The core idea is to iterate through all possible 'y' values and efficiently count the number of 'x' values to its left and the number of 'z' values to its right that satisfy the required conditions.
- Insight 3: Use Binary Indexed Trees (BITs) or Fenwick Trees to efficiently count the number of elements less than or greater than a specific value in a given range.
Complexity Analysis
Time Complexity: O(n*log(n))
Space Complexity: O(n)
Topics
This problem involves: Array, Binary Search, Divide and Conquer, Binary Indexed Tree, Segment Tree, Merge Sort, Ordered Set.
Companies
Asked at: Walmart Labs.