Facebook Pixel

1899. Merge Triplets to Form Target Triplet

Problem Description

You are given a list of triplets (arrays of three integers) and a target triplet. Your goal is to determine if you can obtain the target triplet by performing a specific merge operation on the given triplets.

The Merge Operation:

  • Select any two different triplets at indices i and j
  • Update triplet at index j by taking the maximum of each corresponding position:
    • triplets[j] becomes [max(ai, aj), max(bi, bj), max(ci, cj)]

For example, if you have triplets[i] = [2, 5, 3] and triplets[j] = [1, 7, 5], after the operation, triplets[j] becomes [2, 7, 5] (taking max of each position).

Key Points:

  • You can perform this operation any number of times (including zero times)
  • The operation always updates one triplet by taking element-wise maximums with another
  • You need to check if the exact target triplet [x, y, z] can appear in the triplets array after any sequence of operations

The Challenge: The merge operation only allows values to increase or stay the same (never decrease) since we're taking maximums. This means if any triplet has a value larger than the corresponding target value, that triplet can never be part of forming the target.

The solution leverages the fact that we only need to consider triplets where all three values are less than or equal to the corresponding target values. Among these valid triplets, we can merge them all together (taking maximum of each position) to see if we can reach exactly the target values.

Return true if the target can be obtained, false otherwise.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight comes from understanding what the merge operation actually does - it can only make values go up (or stay the same), never down. When we merge two triplets, each position takes the maximum value from that position in both triplets.

This means if any triplet has even one value that exceeds the corresponding target value, that triplet becomes "poisonous" - we can never use it because it would push us past our target. For example, if our target is [3, 4, 5] and we have a triplet [2, 6, 4], the middle value 6 is already too large. Any merge involving this triplet would result in a middle value of at least 6, which overshoots our target of 4.

So we need to be selective - we can only work with triplets where ALL three values are less than or equal to the corresponding target values. These are our "safe" triplets.

Now here's the beautiful part: among all these safe triplets, we can freely merge them together without worry. Why? Because:

  1. They're all safe (none exceed the target values)
  2. Merging them can only increase values up to the maximum present
  3. The best we can possibly do is collect the maximum value from each position across all safe triplets

This leads to a greedy strategy:

  • Filter out all unsafe triplets (those with any value exceeding the target)
  • Among the safe triplets, find the maximum value at each position
  • Check if these maximums exactly match our target

If they match, we know we can achieve the target through some sequence of merges. If they don't match (meaning at least one maximum is less than the target), then it's impossible - we can't reach a value that doesn't exist in any of our safe triplets.

The elegance is that we don't need to track the actual sequence of operations or which triplets to merge - we just need to verify that the required values exist in the safe triplets.

Learn more about Greedy patterns.

Solution Approach

The implementation follows a greedy approach that processes all triplets in a single pass:

Step 1: Initialize tracking variables

  • Extract the target values: x, y, z = target
  • Initialize three variables d, e, f = 0, 0, 0 to track the maximum values we can achieve at each position

Step 2: Filter and collect maximums For each triplet [a, b, c] in the input:

  • Check if the triplet is "safe": a <= x and b <= y and c <= z
  • If safe, update our maximums:
    • d = max(d, a) - track the maximum first value
    • e = max(e, b) - track the maximum second value
    • f = max(f, c) - track the maximum third value
  • If not safe (any value exceeds the target), skip this triplet entirely

Step 3: Verify the result

  • After processing all triplets, check if [d, e, f] == target
  • Return true if they match, false otherwise

Why this works:

  • By only considering triplets where all values are <= target, we ensure we never overshoot
  • Taking the maximum at each position simulates the best possible outcome of merging all safe triplets together
  • If the maximums equal the target, we know those exact values exist and can be combined
  • If any maximum is less than the target, it's impossible since that value doesn't exist in any safe triplet

Time Complexity: O(n) where n is the number of triplets - we make a single pass through the array

Space Complexity: O(1) - we only use a constant amount of extra space for variables d, e, and f

The beauty of this solution is its simplicity - rather than tracking complex merge operations, we recognize that we just need to verify whether the required values exist among the triplets that don't exceed our target.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with a concrete example to see how the greedy approach works.

Given:

  • triplets = [[2,5,3], [1,8,4], [1,7,5]]
  • target = [2,7,5]

Step 1: Initialize

  • Extract target values: x=2, y=7, z=5
  • Initialize maximums: d=0, e=0, f=0

Step 2: Process each triplet

Processing triplet [2,5,3]:

  • Check if safe: Is 2≀2? βœ“ Is 5≀7? βœ“ Is 3≀5? βœ“
  • All conditions met, so this triplet is safe
  • Update maximums:
    • d = max(0, 2) = 2
    • e = max(0, 5) = 5
    • f = max(0, 3) = 3
  • Current maximums: [2, 5, 3]

Processing triplet [1,8,4]:

  • Check if safe: Is 1≀2? βœ“ Is 8≀7? βœ—
  • Second value 8 exceeds target value 7, so this triplet is unsafe
  • Skip this triplet entirely (it would "poison" our result)
  • Current maximums remain: [2, 5, 3]

Processing triplet [1,7,5]:

  • Check if safe: Is 1≀2? βœ“ Is 7≀7? βœ“ Is 5≀5? βœ“
  • All conditions met, so this triplet is safe
  • Update maximums:
    • d = max(2, 1) = 2
    • e = max(5, 7) = 7
    • f = max(3, 5) = 5
  • Current maximums: [2, 7, 5]

Step 3: Verify result

  • Final maximums: [2, 7, 5]
  • Target: [2, 7, 5]
  • They match exactly! Return true

Why this worked: The algorithm correctly identified that we could achieve the target by:

  1. Ignoring the "poisonous" triplet [1,8,4] (its middle value 8 would overshoot our target of 7)
  2. Combining the safe triplets [2,5,3] and [1,7,5] through merging
  3. The merge would give us [max(2,1), max(5,7), max(3,5)] = [2,7,5], which is exactly our target

Solution Implementation

1class Solution:
2    def mergeTriplets(self, triplets: List[List[int]], target: List[int]) -> bool:
3        # Extract target values for clarity
4        target_x, target_y, target_z = target
5      
6        # Initialize maximum values for each position that can contribute to target
7        max_first = 0
8        max_second = 0
9        max_third = 0
10      
11        # Iterate through each triplet
12        for first, second, third in triplets:
13            # Only consider triplets where all elements are <= corresponding target elements
14            # This ensures the triplet can potentially contribute without exceeding target
15            if first <= target_x and second <= target_y and third <= target_z:
16                # Track the maximum value achievable at each position
17                max_first = max(max_first, first)
18                max_second = max(max_second, second)
19                max_third = max(max_third, third)
20      
21        # Check if we can achieve exactly the target values
22        return [max_first, max_second, max_third] == target
23
1class Solution {
2    public boolean mergeTriplets(int[][] triplets, int[] target) {
3        // Extract target values for clarity
4        int targetX = target[0];
5        int targetY = target[1]; 
6        int targetZ = target[2];
7      
8        // Track the maximum values we can achieve for each position
9        // by merging valid triplets
10        int maxFirst = 0;
11        int maxSecond = 0;
12        int maxThird = 0;
13      
14        // Iterate through all triplets
15        for (int[] triplet : triplets) {
16            // Extract current triplet values
17            int currentFirst = triplet[0];
18            int currentSecond = triplet[1];
19            int currentThird = triplet[2];
20          
21            // Only consider triplets where all values are less than or equal to target
22            // This ensures we never exceed the target when merging
23            if (currentFirst <= targetX && currentSecond <= targetY && currentThird <= targetZ) {
24                // Update maximum achievable values by taking max operation
25                // This simulates the merge operation where we take max of each position
26                maxFirst = Math.max(maxFirst, currentFirst);
27                maxSecond = Math.max(maxSecond, currentSecond);
28                maxThird = Math.max(maxThird, currentThird);
29            }
30        }
31      
32        // Check if we can achieve exactly the target triplet
33        return maxFirst == targetX && maxSecond == targetY && maxThird == targetZ;
34    }
35}
36
1class Solution {
2public:
3    bool mergeTriplets(vector<vector<int>>& triplets, vector<int>& target) {
4        // Extract target values for clarity
5        int targetX = target[0];
6        int targetY = target[1]; 
7        int targetZ = target[2];
8      
9        // Track the maximum achievable values for each position
10        int maxFirst = 0;
11        int maxSecond = 0;
12        int maxThird = 0;
13      
14        // Iterate through all triplets
15        for (const auto& triplet : triplets) {
16            int first = triplet[0];
17            int second = triplet[1];
18            int third = triplet[2];
19          
20            // Only consider triplets where all values are <= target values
21            // This ensures we never exceed the target when merging
22            if (first <= targetX && second <= targetY && third <= targetZ) {
23                // Update maximum achievable values
24                maxFirst = max(maxFirst, first);
25                maxSecond = max(maxSecond, second);
26                maxThird = max(maxThird, third);
27            }
28        }
29      
30        // Check if we can achieve exactly the target values
31        return maxFirst == targetX && maxSecond == targetY && maxThird == targetZ;
32    }
33};
34
1/**
2 * Determines if we can form the target triplet by merging valid triplets.
3 * A triplet can be merged if all its values are less than or equal to the corresponding target values.
4 * The merge operation takes the maximum value at each position from selected triplets.
5 * 
6 * @param triplets - Array of triplets where each triplet contains three numbers
7 * @param target - Target triplet to achieve through merging
8 * @returns true if target can be formed by merging valid triplets, false otherwise
9 */
10function mergeTriplets(triplets: number[][], target: number[]): boolean {
11    // Destructure target triplet into individual components
12    const [targetX, targetY, targetZ] = target;
13  
14    // Initialize the maximum values we can achieve at each position
15    let maxX: number = 0;
16    let maxY: number = 0;
17    let maxZ: number = 0;
18  
19    // Iterate through each triplet
20    for (const [currentX, currentY, currentZ] of triplets) {
21        // Check if current triplet is valid (all values <= corresponding target values)
22        if (currentX <= targetX && currentY <= targetY && currentZ <= targetZ) {
23            // Update maximum achievable values at each position
24            maxX = Math.max(maxX, currentX);
25            maxY = Math.max(maxY, currentY);
26            maxZ = Math.max(maxZ, currentZ);
27        }
28    }
29  
30    // Check if we can achieve the exact target values
31    return maxX === targetX && maxY === targetY && maxZ === targetZ;
32}
33

Time and Space Complexity

Time Complexity: O(n) where n is the number of triplets in the input list. The algorithm iterates through the triplets list exactly once, performing constant-time operations (comparisons and max operations) for each triplet.

Space Complexity: O(1) as the algorithm only uses a fixed amount of extra space regardless of the input size. The variables x, y, z, d, e, and f are the only additional space used, which remains constant irrespective of the number of triplets.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

Pitfall 1: Attempting to Track Individual Merge Operations

The Problem: Many developers initially try to simulate the actual merge operations by maintaining which triplets have been merged and tracking the intermediate states. This leads to overly complex code with nested loops and unnecessary state management.

# Incorrect approach - trying to simulate actual merges
def mergeTriplets_wrong(triplets, target):
    n = len(triplets)
    merged = [False] * n
  
    # Try to simulate merging process
    for i in range(n):
        for j in range(n):
            if i != j and not merged[i]:
                # Attempt to merge and track state
                new_triplet = [max(triplets[i][k], triplets[j][k]) for k in range(3)]
                triplets[j] = new_triplet
                merged[i] = True
                if triplets[j] == target:
                    return True
    return False

The Solution: Recognize that you don't need to track the actual merge sequence. Since merging only increases values (or keeps them the same), you can simply collect the maximum achievable value at each position from all valid triplets.

Pitfall 2: Not Filtering Out Invalid Triplets Early

The Problem: Some solutions try to use all triplets and then check if the result exceeds the target, leading to incorrect results:

# Incorrect - doesn't filter out triplets that exceed target
def mergeTriplets_wrong2(triplets, target):
    max_vals = [0, 0, 0]
  
    for triplet in triplets:
        # Wrong: merging without checking if values exceed target
        for i in range(3):
            max_vals[i] = max(max_vals[i], triplet[i])
  
    # This could result in values greater than target
    return max_vals == target

The Solution: Always check if ALL three values in a triplet are less than or equal to their corresponding target values before considering that triplet. If even one value exceeds the target, that triplet can never be part of the solution.

Pitfall 3: Checking Only Partial Conditions

The Problem: Some implementations check if individual values match the target without ensuring all three conditions are met simultaneously:

# Incorrect - checking conditions separately
def mergeTriplets_wrong3(triplets, target):
    found_x = False
    found_y = False
    found_z = False
  
    for a, b, c in triplets:
        if a == target[0]:
            found_x = True
        if b == target[1]:
            found_y = True
        if c == target[2]:
            found_z = True
  
    return found_x and found_y and found_z

This fails because it doesn't ensure that valid values can be combined together. For example, if one triplet is [3, 1, 1] and another is [1, 3, 1], and the target is [3, 3, 2], this wrong approach would return True even though we can never achieve the target value of 2 in the third position.

The Solution: Track the maximum achievable value at each position, but only from triplets where ALL values are within bounds. This ensures that the values you're tracking can actually be merged together to potentially form the target.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which two pointer techniques do you use to check if a string is a palindrome?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More