Description

給定一個二維陣列 triplets(每個元素為 [a, b, c])和一個目標 target = [x, y, z]。可以選擇任意兩個 triplets 做 merge(逐位取 max)。判斷是否能透過若干次 merge 得到 target。

Example:

Input: triplets = [[2,5,3],[1,8,4],[1,7,5]], target = [2,7,5] Output: true (選 [2,5,3] 和 [1,7,5] merge 得 [2,7,5])

Intuition#

過濾掉任一維度超過 target 的 triplet(因為 max 只會讓值變大),剩下的看能否湊齊 target 的每一維。

  • Merge 操作是逐位取 max,一旦某個維度超過 target 就不可能回頭
  • 所以只保留三個維度都 <= target 對應值的 triplets
  • 在合法的 triplets 中,看是否每個維度都有某個 triplet 恰好等於 target 的該維度值

Approaches#

1: 暴力檢查所有子集#

  • 概念: 對所有合法 triplets 的子集嘗試 merge,看是否能得到 target。
  • 時間複雜度: O(2^n) 最差情況
  • 空間複雜度: O(1)
class Solution {
    fun mergeTriplets(triplets: Array<IntArray>, target: IntArray): Boolean {
        val valid = triplets.filter {
            it[0] <= target[0] && it[1] <= target[1] && it[2] <= target[2]
        }
        // 嘗試所有子集
        val n = valid.size
        for (mask in 1 until (1 shl n)) {
            val merged = intArrayOf(0, 0, 0)
            for (i in 0 until n) {
                if (mask and (1 shl i) != 0) {
                    for (k in 0..2) merged[k] = maxOf(merged[k], valid[i][k])
                }
            }
            if (merged.contentEquals(target)) return true
        }
        return false
    }
}

⭐2: Greedy(一次遍歷)#

  • 概念: 過濾合法 triplets 後,只需檢查每個維度是否存在等於 target 的值。用一個 Set 記錄哪些維度已經被滿足。
  • 時間複雜度: O(n)
  • 空間複雜度: O(1)
class Solution {
    fun mergeTriplets(triplets: Array<IntArray>, target: IntArray): Boolean {
        val found = BooleanArray(3)
        for (t in triplets) {
            if (t[0] <= target[0] && t[1] <= target[1] && t[2] <= target[2]) {
                for (k in 0..2) {
                    if (t[k] == target[k]) found[k] = true
                }
            }
        }
        return found[0] && found[1] && found[2]
    }
}

🔑 Takeaways#

  • Pattern: 貪心過濾 — 先排除不可能的候選者,再驗證可行性
  • 關鍵技巧: merge(逐位取 max)的單調性是關鍵:值只能增不能減,所以超過 target 的 triplet 直接淘汰