2475. Number of Unequal Triplets in Array
Problem Description
You are given an array of positive integers nums
that is 0-indexed. Your task is to count how many triplets of indices (i, j, k)
satisfy specific conditions.
For a valid triplet (i, j, k)
, the following must be true:
-
Index ordering: The indices must be in strictly increasing order, meaning
0 <= i < j < k < nums.length
. This ensures we're selecting three different positions from the array. -
Pairwise distinct values: The values at these three positions must all be different from each other. Specifically:
nums[i] != nums[j]
(first and second values are different)nums[i] != nums[k]
(first and third values are different)nums[j] != nums[k]
(second and third values are different)
The solution uses a brute force approach with three nested loops to check every possible combination of three indices. For each combination where i < j < k
, it checks if all three values are different from each other. If they are, it increments the count. The time complexity is O(nΒ³)
where n
is the length of the array, as we examine all possible triplets.
For example, if nums = [4, 4, 2, 4, 3]
, valid triplets would include (0, 2, 4)
because nums[0] = 4
, nums[2] = 2
, and nums[4] = 3
are all different from each other.
Intuition
When we need to find all valid triplets from an array, the most straightforward approach is to examine every possible combination of three elements. Since we need to check specific conditions for each triplet, we can systematically generate all possible triplets and verify if they meet our requirements.
The key insight is that we need three distinct positions i < j < k
, and for each such triplet of positions, we need to check if the values at these positions are all different. This naturally leads to a three-level nested loop structure:
- The outer loop picks the first position
i
- The middle loop picks the second position
j
(starting fromi + 1
to ensurej > i
) - The inner loop picks the third position
k
(starting fromj + 1
to ensurek > j
)
This way, we automatically satisfy the ordering constraint i < j < k
through our loop structure. For each generated triplet, we then only need to verify that the three values are pairwise distinct.
The brute force approach works well here because:
- We need to examine relationships between three elements, which inherently requires looking at combinations
- The constraint checking is simple - just comparing three values for inequality
- There's no obvious pattern or mathematical property that would allow us to count valid triplets without examining them
We could optimize this further by using frequency counting or other techniques, but the brute force solution is clear, correct, and easy to implement. It directly translates the problem requirements into code: generate all ordered triplets and count those where all three values are different.
Learn more about Sorting patterns.
Solution Approach
The implementation uses a brute force enumeration approach with three nested loops to check all possible triplets.
Algorithm Steps:
-
Initialize counter: Start with
ans = 0
to keep track of valid triplets. -
Triple nested loops:
- First loop:
for i in range(n)
- iterates through all possible first positions - Second loop:
for j in range(i + 1, n)
- iterates through all positions afteri
- Third loop:
for k in range(j + 1, n)
- iterates through all positions afterj
- First loop:
-
Condition checking: For each triplet
(i, j, k)
, check if all three values are pairwise distinct:nums[i] != nums[j] and nums[j] != nums[k] and nums[i] != nums[k]
-
Count valid triplets: The expression in step 3 evaluates to
True
(which equals 1) when all conditions are met, orFalse
(which equals 0) otherwise. Adding this boolean result toans
effectively counts the valid triplets:ans += (nums[i] != nums[j] and nums[j] != nums[k] and nums[i] != nums[k])
Key Implementation Details:
- The loop structure
i < j < k
is maintained by starting each inner loop from the previous index + 1 - Python's boolean-to-integer conversion is utilized:
True
becomes 1 andFalse
becomes 0 when added to an integer - No additional data structures are needed - just the counter variable
ans
- Time complexity:
O(nΒ³)
as we examine allC(n, 3)
possible triplets - Space complexity:
O(1)
as we only use a constant amount of extra space
This straightforward implementation directly translates the problem requirements into code without any optimization tricks, making it easy to understand and verify for correctness.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with nums = [1, 3, 1, 5, 4]
.
We need to find all triplets (i, j, k)
where i < j < k
and the values at these positions are all different.
Step-by-step execution:
Iteration 1: i = 0 (nums[0] = 1)
- j = 1, k = 2: Check (0, 1, 2) β nums[0]=1, nums[1]=3, nums[2]=1 β 1β 3 β, 3β 1 β, but 1=1 β β Not valid
- j = 1, k = 3: Check (0, 1, 3) β nums[0]=1, nums[1]=3, nums[3]=5 β 1β 3 β, 3β 5 β, 1β 5 β β Valid! Count = 1
- j = 1, k = 4: Check (0, 1, 4) β nums[0]=1, nums[1]=3, nums[4]=4 β 1β 3 β, 3β 4 β, 1β 4 β β Valid! Count = 2
- j = 2, k = 3: Check (0, 2, 3) β nums[0]=1, nums[2]=1, nums[3]=5 β 1=1 β β Not valid
- j = 2, k = 4: Check (0, 2, 4) β nums[0]=1, nums[2]=1, nums[4]=4 β 1=1 β β Not valid
- j = 3, k = 4: Check (0, 3, 4) β nums[0]=1, nums[3]=5, nums[4]=4 β 1β 5 β, 5β 4 β, 1β 4 β β Valid! Count = 3
Iteration 2: i = 1 (nums[1] = 3)
- j = 2, k = 3: Check (1, 2, 3) β nums[1]=3, nums[2]=1, nums[3]=5 β 3β 1 β, 1β 5 β, 3β 5 β β Valid! Count = 4
- j = 2, k = 4: Check (1, 2, 4) β nums[1]=3, nums[2]=1, nums[4]=4 β 3β 1 β, 1β 4 β, 3β 4 β β Valid! Count = 5
- j = 3, k = 4: Check (1, 3, 4) β nums[1]=3, nums[3]=5, nums[4]=4 β 3β 5 β, 5β 4 β, 3β 4 β β Valid! Count = 6
Iteration 3: i = 2 (nums[2] = 1)
- j = 3, k = 4: Check (2, 3, 4) β nums[2]=1, nums[3]=5, nums[4]=4 β 1β 5 β, 5β 4 β, 1β 4 β β Valid! Count = 7
Iteration 4: i = 3 (nums[3] = 5)
- No valid j exists since j must be < 4 and k must be < 5 (array length)
Final Result: 7 valid triplets
The algorithm systematically checks all possible combinations where indices increase (i < j < k) and counts those where all three values differ. The three nested loops ensure we examine every possible triplet exactly once.
Solution Implementation
1class Solution:
2 def unequalTriplets(self, nums: List[int]) -> int:
3 """
4 Count the number of triplets (i, j, k) where i < j < k
5 and nums[i], nums[j], and nums[k] are all different.
6
7 Args:
8 nums: List of integers
9
10 Returns:
11 Number of valid unequal triplets
12 """
13 n = len(nums)
14 count = 0
15
16 # Iterate through all possible triplets with indices i < j < k
17 for i in range(n):
18 for j in range(i + 1, n):
19 for k in range(j + 1, n):
20 # Check if all three elements are pairwise different
21 if nums[i] != nums[j] and nums[j] != nums[k] and nums[i] != nums[k]:
22 count += 1
23
24 return count
25
1class Solution {
2 /**
3 * Counts the number of triplets (i, j, k) where i < j < k and
4 * nums[i], nums[j], and nums[k] are all different.
5 *
6 * @param nums The input array of integers
7 * @return The count of unequal triplets
8 */
9 public int unequalTriplets(int[] nums) {
10 int arrayLength = nums.length;
11 int tripletCount = 0;
12
13 // Iterate through all possible triplet combinations
14 // First element of triplet
15 for (int i = 0; i < arrayLength; i++) {
16 // Second element of triplet (must be after first)
17 for (int j = i + 1; j < arrayLength; j++) {
18 // Third element of triplet (must be after second)
19 for (int k = j + 1; k < arrayLength; k++) {
20 // Check if all three elements are different
21 if (nums[i] != nums[j] &&
22 nums[j] != nums[k] &&
23 nums[i] != nums[k]) {
24 tripletCount++;
25 }
26 }
27 }
28 }
29
30 return tripletCount;
31 }
32}
33
1class Solution {
2public:
3 int unequalTriplets(vector<int>& nums) {
4 int size = nums.size();
5 int count = 0;
6
7 // Iterate through all possible triplets (i, j, k) where i < j < k
8 for (int i = 0; i < size; ++i) {
9 for (int j = i + 1; j < size; ++j) {
10 for (int k = j + 1; k < size; ++k) {
11 // Check if all three elements are pairwise distinct
12 if (nums[i] != nums[j] &&
13 nums[j] != nums[k] &&
14 nums[i] != nums[k]) {
15 ++count;
16 }
17 }
18 }
19 }
20
21 return count;
22 }
23};
24
1/**
2 * Counts the number of triplets (i, j, k) where all three elements are different
3 * @param nums - Array of integers
4 * @returns Number of valid unequal triplets
5 */
6function unequalTriplets(nums: number[]): number {
7 // Get the length of the input array
8 const arrayLength: number = nums.length;
9
10 // Initialize counter for valid triplets
11 let tripletCount: number = 0;
12
13 // First loop: iterate through potential first elements of triplets
14 // Stop at arrayLength - 2 to ensure space for j and k
15 for (let i: number = 0; i < arrayLength - 2; i++) {
16
17 // Second loop: iterate through potential second elements of triplets
18 // Start from i + 1 to avoid duplicates, stop at arrayLength - 1 to ensure space for k
19 for (let j: number = i + 1; j < arrayLength - 1; j++) {
20
21 // Third loop: iterate through potential third elements of triplets
22 // Start from j + 1 to maintain order and avoid duplicates
23 for (let k: number = j + 1; k < arrayLength; k++) {
24
25 // Check if all three elements at indices i, j, k are different
26 if (nums[i] !== nums[j] && nums[j] !== nums[k] && nums[i] !== nums[k]) {
27 // Increment counter when a valid triplet is found
28 tripletCount++;
29 }
30 }
31 }
32 }
33
34 // Return the total count of valid unequal triplets
35 return tripletCount;
36}
37
Time and Space Complexity
The time complexity is O(nΒ³)
, where n
is the length of the array nums
. This is because the code uses three nested loops: the outer loop runs n
times, the middle loop runs up to n-1
times for each iteration of the outer loop, and the inner loop runs up to n-2
times for each iteration of the middle loop. In the worst case, this results in approximately n * (n-1) * (n-2) / 6
iterations, which simplifies to O(nΒ³)
.
The space complexity is O(1)
. The algorithm only uses a constant amount of extra space to store the variables n
, ans
, i
, j
, and k
, regardless of the input size. No additional data structures that scale with the input are created.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Index Range in Nested Loops
A common mistake is setting up the loop ranges incorrectly, which can lead to either missing valid triplets or counting duplicates.
Incorrect Implementation:
# Wrong: Using wrong starting points
for i in range(n):
for j in range(n): # Should start from i+1
for k in range(n): # Should start from j+1
if i < j < k and nums[i] != nums[j] != nums[k]:
count += 1
Problem: This wastes iterations checking invalid index combinations and requires additional logic to ensure i < j < k
.
Correct Approach:
for i in range(n):
for j in range(i + 1, n): # Start from i+1
for k in range(j + 1, n): # Start from j+1
# No need to check i < j < k since it's guaranteed by loop structure
2. Incorrect Pairwise Comparison Logic
Another frequent error is using chained inequality operators incorrectly for checking distinctness.
Incorrect Implementation:
# Wrong: This doesn't check all pairwise differences if nums[i] != nums[j] != nums[k]: count += 1
Problem: The expression nums[i] != nums[j] != nums[k]
in Python means (nums[i] != nums[j]) and (nums[j] != nums[k])
. This doesn't check if nums[i] != nums[k]
. For example, if nums[i] = 1, nums[j] = 2, nums[k] = 1
, the condition would pass even though nums[i] == nums[k]
.
Correct Approach:
# Explicitly check all three pairs if nums[i] != nums[j] and nums[j] != nums[k] and nums[i] != nums[k]: count += 1
3. Off-by-One Errors in Loop Bounds
Incorrect Implementation:
# Wrong: Missing the last element
for i in range(n-2):
for j in range(i + 1, n-1):
for k in range(j + 1, n):
Problem: The first loop should go up to n-2
(inclusive) since we need at least 3 elements, but writing range(n-3)
would miss valid triplets.
Correct Approach:
# Can use full range and let inner loops handle bounds
for i in range(n):
for j in range(i + 1, n):
for k in range(j + 1, n):
# Or optimize slightly:
for i in range(n - 2): # Stop when less than 3 elements remain
for j in range(i + 1, n - 1): # Stop when less than 2 elements remain
for k in range(j + 1, n):
4. Performance Consideration for Large Arrays
While not a logical error, using the O(nΒ³) brute force approach on large arrays can cause timeouts.
Alternative Optimization Using Frequency Count:
def unequalTriplets(self, nums: List[int]) -> int:
from collections import Counter
freq = Counter(nums)
if len(freq) < 3:
return 0
result = 0
prev = 0
next_count = len(nums)
for count in freq.values():
next_count -= count
result += prev * count * next_count
prev += count
return result
This optimized solution runs in O(n) time by counting frequencies and calculating combinations mathematically.
Consider the classic dynamic programming of longest increasing subsequence:
Find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order.
For example, the length of LIS for [50, 3, 10, 7, 40, 80]
is 4
and LIS is
[3, 7, 40, 80]
.
What is the recurrence relation?
Recommended Readings
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!