<p>A <strong>triplet</strong> is an array of three integers. You are given a 2D integer array <code>triplets</code>, where <code>triplets[i] = [a<sub>i</sub>, b<sub>i</sub>, c<sub>i</sub>]</code> describes the <code>i<sup>th</sup></code> <strong>triplet</strong>. You are also given an integer array <code>target = [x, y, z]</code> that describes the <strong>triplet</strong> you want to obtain.</p>

<p>To obtain <code>target</code>, you may apply the following operation on <code>triplets</code> <strong>any number</strong> of times (possibly <strong>zero</strong>):</p>

<ul>
	<li>Choose two indices (<strong>0-indexed</strong>) <code>i</code> and <code>j</code> (<code>i != j</code>) and <strong>update</strong> <code>triplets[j]</code> to become <code>[max(a<sub>i</sub>, a<sub>j</sub>), max(b<sub>i</sub>, b<sub>j</sub>), max(c<sub>i</sub>, c<sub>j</sub>)]</code>.

	<ul>
		<li>For example, if <code>triplets[i] = [2, 5, 3]</code> and <code>triplets[j] = [1, 7, 5]</code>, <code>triplets[j]</code> will be updated to <code>[max(2, 1), max(5, 7), max(3, 5)] = [2, 7, 5]</code>.</li>
	</ul>
	</li>
</ul>

<p>Return <code>true</code> <em>if it is possible to obtain the </em><code>target</code><em> <strong>triplet</strong> </em><code>[x, y, z]</code><em> as an<strong> element</strong> of </em><code>triplets</code><em>, or </em><code>false</code><em> otherwise</em>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> triplets = [[2,5,3],[1,8,4],[1,7,5]], target = [2,7,5]
<strong>Output:</strong> true
<strong>Explanation:</strong> Perform the following operations:
- Choose the first and last triplets [<u>[2,5,3]</u>,[1,8,4],<u>[1,7,5]</u>]. Update the last triplet to be [max(2,1), max(5,7), max(3,5)] = [2,7,5]. triplets = [[2,5,3],[1,8,4],<u>[2,7,5]</u>]
The target triplet [2,7,5] is now an element of triplets.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> triplets = [[3,4,5],[4,5,6]], target = [3,2,5]
<strong>Output:</strong> false
<strong>Explanation:</strong> It is impossible to have [3,2,5] as an element because there is no 2 in any of the triplets.
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> triplets = [[2,5,3],[2,3,4],[1,2,5],[5,2,3]], target = [5,5,5]
<strong>Output:</strong> true
<strong>Explanation: </strong>Perform the following operations:
- Choose the first and third triplets [<u>[2,5,3]</u>,[2,3,4],<u>[1,2,5]</u>,[5,2,3]]. Update the third triplet to be [max(2,1), max(5,2), max(3,5)] = [2,5,5]. triplets = [[2,5,3],[2,3,4],<u>[2,5,5]</u>,[5,2,3]].
- Choose the third and fourth triplets [[2,5,3],[2,3,4],<u>[2,5,5]</u>,<u>[5,2,3]</u>]. Update the fourth triplet to be [max(2,5), max(5,2), max(5,3)] = [5,5,5]. triplets = [[2,5,3],[2,3,4],[2,5,5],<u>[5,5,5]</u>].
The target triplet [5,5,5] is now an element of triplets.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= triplets.length &lt;= 10<sup>5</sup></code></li>
	<li><code>triplets[i].length == target.length == 3</code></li>
	<li><code>1 &lt;= a<sub>i</sub>, b<sub>i</sub>, c<sub>i</sub>, x, y, z &lt;= 1000</code></li>
</ul>

class Solution:
    # Time: O(n)
    # Space: O(n)
    def mergeTriplets(self, triplets: List[List[int]], target: List[int]) -> bool:
        # we do three rounds of filtering, after each round we'll get a resulting list of triplets that
        # (1) only contains digit a and under
        # (2) the above, and only contains digit b and under
        # (3) the above, and only contains digit c and under
        # => in the end if the resulting list has at least 1 exact match of each a, b and c => we can make a target triplet

        # note that there are 2 main tasks: filtering, and making sure we have one of each target digit

        # filtering step explanation/ proof
        # at the first digit digit, a less than equal filter must be used because if we let a digit that's greater than a pass through,
        # that triplet may only be useful if the other two digits b or c match the target
        # however, we can't ever use these use digits because if we use it with another triplet that has digit a <= target a, the greater, wrong digit a will always win
        # => it will be useless anyway and the first filter must be applied
        # similar logic to filter b and c

        # proof of having at least 1 of target a, b, c means success
        # - since we already have at least 1 match of a => 4 subcases:
        #   - this triplet already has b and c => success
        #   - has b but not c => shuffle with another triplet that has c
        #       - since our triplet doesn't have c, it must have a digit less than c because of filter (3) => get c
        #       - furthermore, the other triplets must have only digit a or less because of filter (1) and b or less because of filter (2)
        #       - => we'll stil have a and b in the result => success
        #   - has c but not b => similar solution as above
        #   - does't match neither b nor c =>
        #       - shuffle with another triplet that has b. since our triplet doesn't have c, it must have a digit less than c because of filter (3) => get c
        #       - furthermore, the other triplets must have only digit a or less because of filter (1) => still have a in the resulting triplet
        #       - now we have a resulting triplet that matches a and b
        #       - now if c matches by chance => success. if not, we're back to the 2nd scenario, has b but not c

        # 3 rounds of filtering, each round keeping only triplets whose ith digit <= target's ith digit
        # for i, target_digit in enumerate(target):  # O(n)
        #     triplets = [triplet for triplet in triplets if triplet[i] <= target_digit]

        # # confirm the remaining list of triplets contains at least 1 of each target a, b and c
        # has_a = has_b = has_c = False
        # target_a, target_b, target_c = target
        # for a, b, c in triplets:  # O(n)
        #     if a == target_a:
        #         has_a = True
        #     if b == target_b:
        #         has_b = True
        #     if c == target_c:
        #         has_c = True

        # return has_a and has_b and has_c


        for i, target_digit in enumerate(target[:2]):  # O(n)
            triplets = [triplet for triplet in triplets if triplet[i] <= target_digit]

        has_a = has_b = has_c = False
        target_a, target_b, target_c = target
        for a, b, c in triplets:
            if c > target_c:
                continue
            if a == target_a:
                has_a = True
            if b == target_b:
                has_b = True
            if c == target_c:
                has_c = True

        return has_a and has_b and has_c


60300