Skip to content

1354. Construct Target Array With Multiple Sums

Description

You are given an array target of n integers. From a starting array arr consisting of n 1's, you may perform the following procedure :

  • let x be the sum of all elements currently in your array.
  • choose index i, such that 0 <= i < n and set the value of arr at index i to x.
  • You may repeat this procedure as many times as needed.

Return true if it is possible to construct the target array from arr, otherwise, return false.

 

Example 1:

Input: target = [9,3,5]
Output: true
Explanation: Start with arr = [1, 1, 1] 
[1, 1, 1], sum = 3 choose index 1
[1, 3, 1], sum = 5 choose index 2
[1, 3, 5], sum = 9 choose index 0
[9, 3, 5] Done

Example 2:

Input: target = [1,1,1,2]
Output: false
Explanation: Impossible to create target array from [1,1,1,1].

Example 3:

Input: target = [8,5]
Output: true

 

Constraints:

  • n == target.length
  • 1 <= n <= 5 * 104
  • 1 <= target[i] <= 109

Solutions

Solution 1: Reverse Construction + Priority Queue (Max Heap)

We observe that if we start constructing the target array \(\textit{target}\) from the array \(\textit{arr}\) in a forward manner, it is difficult to determine which index \(i\) to choose each time, making the problem quite complex. However, if we construct in reverse starting from the array \(\textit{target}\), each construction step must select the largest element in the current array, which ensures that each construction is unique, making the problem relatively simple.

Therefore, we can use a priority queue (max heap) to store the elements of array \(\textit{target}\), and use a variable \(s\) to record the sum of all elements in array \(\textit{target}\). Each time we extract the maximum element \(mx\) from the priority queue and calculate the sum \(t\) of all elements in the current array except \(mx\). If \(t \lt 1\) or \(mx - t \lt 1\), it means the target array \(\textit{target}\) cannot be constructed, and we return false. Otherwise, we calculate \(mx \bmod t\). If \(mx \bmod t = 0\), we set \(x = t\); otherwise, we set \(x = mx \bmod t\). We add \(x\) to the priority queue and update the value of \(s\). We repeat this process until all elements in the priority queue become \(1\), at which point we return true.

The time complexity is \(O(n \log n)\) and the space complexity is \(O(n)\), where \(n\) is the length of array \(\textit{target}\).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution:
    def isPossible(self, target: List[int]) -> bool:
        s = sum(target)
        pq = [-x for x in target]
        heapify(pq)
        while -pq[0] > 1:
            mx = -heappop(pq)
            t = s - mx
            if t == 0 or mx - t < 1:
                return False
            x = (mx % t) or t
            heappush(pq, -x)
            s = s - mx + x
        return True
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
    public boolean isPossible(int[] target) {
        PriorityQueue<Long> pq = new PriorityQueue<>(Collections.reverseOrder());
        long s = 0;
        for (int x : target) {
            s += x;
            pq.offer((long) x);
        }
        while (pq.peek() > 1) {
            long mx = pq.poll();
            long t = s - mx;
            if (t == 0 || mx - t < 1) {
                return false;
            }
            long x = mx % t;
            if (x == 0) {
                x = t;
            }
            pq.offer(x);
            s = s - mx + x;
        }
        return true;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
    bool isPossible(vector<int>& target) {
        priority_queue<int> pq;
        long long s = 0;
        for (int i = 0; i < target.size(); i++) {
            s += target[i];
            pq.push(target[i]);
        }
        while (pq.top() != 1) {
            int mx = pq.top();
            pq.pop();
            long long t = s - mx;
            if (t < 1 || mx - t < 1) {
                return false;
            }
            int x = mx % t;
            if (x == 0) {
                x = t;
            }
            pq.push(x);
            s = s - mx + x;
        }
        return true;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
func isPossible(target []int) bool {
    pq := &hp{target}
    s := 0
    for _, x := range target {
        s += x
    }
    heap.Init(pq)
    for target[0] > 1 {
        mx := target[0]
        t := s - mx
        if t < 1 || mx-t < 1 {
            return false
        }
        x := mx % t
        if x == 0 {
            x = t
        }
        target[0] = x
        heap.Fix(pq, 0)
        s = s - mx + x
    }
    return true
}

type hp struct{ sort.IntSlice }

func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] }
func (hp) Pop() (_ any)         { return }
func (hp) Push(any)             {}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
function isPossible(target: number[]): boolean {
    const pq = new MaxPriorityQueue<number>();
    let s = 0;
    for (const x of target) {
        s += x;
        pq.enqueue(x);
    }
    while (pq.front() > 1) {
        const mx = pq.dequeue();
        const t = s - mx;
        if (t < 1 || mx - t < 1) {
            return false;
        }
        const x = mx % t || t;
        pq.enqueue(x);
        s = s - mx + x;
    }
    return true;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
use std::collections::BinaryHeap;

impl Solution {
    pub fn is_possible(target: Vec<i32>) -> bool {
        let mut pq = BinaryHeap::from(target.clone());
        let mut s: i64 = target.iter().map(|&x| x as i64).sum();

        while let Some(&mx) = pq.peek() {
            if mx == 1 {
                break;
            }
            let mx = pq.pop().unwrap() as i64;
            let t = s - mx;
            if t < 1 || mx - t < 1 {
                return false;
            }
            let x = if mx % t == 0 { t } else { mx % t };
            pq.push(x as i32);
            s = s - mx + x;
        }
        true
    }
}

Comments