Skip to main content

Zero Array Transformation III - Solution & Explanation

MediumArrayGreedySortingHeap (Priority Queue)20 min readAsked at: Amazon, Microsoft, Meta +2
Practice this problem

Problem Statement

You are given an integer array nums of length n and a 2D array queries where queries[i] = [li, ri].

Each queries[i] represents the following action on nums:

  • Decrement the value at each index in the range [li, ri] in nums by at most 1.
  • The amount by which the value is decremented can be chosen independently for each index.

A Zero Array is an array with all its elements equal to 0.

Return the maximum number of elements that can be removed from queries, such that nums can still be converted to a zero array using the remaining queries. If it is not possible to convert nums to a zero array, return -1.

 

Example 1:

Input: nums = [2,0,2], queries = [[0,2],[0,2],[1,1]]

Output: 1

Explanation:

After removing queries[2], nums can still be converted to a zero array.

  • Using queries[0], decrement nums[0] and nums[2] by 1 and nums[1] by 0.
  • Using queries[1], decrement nums[0] and nums[2] by 1 and nums[1] by 0.

Example 2:

Input: nums = [1,1,1,1], queries = [[1,3],[0,2],[1,3],[1,2]]

Output: 2

Explanation:

We can remove queries[2] and queries[3].

Example 3:

Input: nums = [1,2,3,4], queries = [[0,3]]

Output: -1

Explanation:

nums cannot be converted to a zero array even after using all the queries.

 

Constraints:

  • 1 <= nums.length <= 105
  • 0 <= nums[i] <= 105
  • 1 <= queries.length <= 105
  • queries[i].length == 2
  • 0 <= li <= ri < nums.length

Approach Overview

Problem Overview: You are given an array nums and a list of range queries. Each query can decrease every element in its range by 1. The goal is to determine how many queries can be removed while still being able to apply the remaining queries to make the entire array become zero.

Approach 1: Difference Array Technique (O((n + q) log q) time, O(n + q) space)

This approach simulates applying only the necessary queries using a difference array to track how many decrements are currently active at each index. Sort queries by their starting index and iterate through nums from left to right. Maintain a max heap of candidate queries whose start index is ≤ the current position. If the active decrement count is smaller than nums[i], repeatedly pick the query with the farthest right boundary from the heap and apply it. Applying a query increases the active decrement count and schedules its end using the difference array (diff[r+1]--). This ensures decrements automatically stop after the range ends. If no valid query covers the index while more decrements are needed, the transformation is impossible. The number of used queries determines how many can be removed.

The key insight is that applying the query with the farthest r maximizes coverage for future indices. This greedy choice reduces the total number of queries needed and works well with prefix-sum style tracking using a prefix sum or difference array.

Approach 2: Greedy with Priority Queue (O((n + q) log q) time, O(q) space)

This method focuses directly on greedy selection using a max heap. First sort queries by their left boundary. While scanning the array, push all queries whose l ≤ i into a max heap ordered by r. Track how many decrement operations are currently active at index i. If nums[i] requires more decrements than currently active, repeatedly pop the query with the largest r and activate it. Queries that end before i cannot help and indicate failure if additional decrements are still required.

The greedy choice works because a query with a larger right boundary contributes decrements to more future elements. This approach combines concepts from greedy algorithms and priority queues. By always extending coverage as far as possible, you minimize the number of queries used.

Recommended for interviews: The greedy priority queue solution is what most interviewers expect. It clearly demonstrates reasoning about optimal choices and efficient data structure usage. Showing the difference-array tracking alongside it demonstrates strong understanding of range updates and array prefix techniques.

Approach 1: Difference Array Technique

The goal is to reduce the nums array to all zeros using the fewest possible queries. To efficiently adjust multiple ranges in the nums array, we can employ a 'difference array' to record the increment/decrement at particular indices. This allows constant-time updates over a subrange.

Once the necessary decrements for each range are calculated, test different combinations of queries to find the maximal number of query removals that still result in nums becoming all zeros.

This code applies the difference array technique. It processes the queries to adjust the nums array, then tests all subarrays of the query sequences by removing one query at a time. If zero array can be achieved by skipped queries, it outputs the number of skippable queries. The approach is greedy – trying minimal number of changes until zero array is possible.

Code

Python

JavaScript

Complexity

Time Complexity: O(M * N), where N is the length of nums and M is the number of queries since we attempt each query removal.

Space Complexity: O(N) for the difference array.

Try this approach in the editor →

Approach 2: Greedy with Priority Queue

This approach involves treating queries in a greedily prioritized manner. Using a priority queue to always select and process a query that maximizes the zero effect over the largest overlapping range just after it processes the overlapping range, thus allowing maximum flexibility in decrements.

The C++ solution employs a min-heap to greedily select the smallest possible range query to remove, ensuring efficiency by always considering the next largest decrement range effectively. This ensures that minimal queries are used to zero the nums array, while making sure a removal is beneficial.

Code

C++

Complexity

Time Complexity: O(N log N) (due to the heap operations).

Space Complexity: O(N).

Try this approach in the editor →

Approach 3: Greedy + Difference Array + Priority Queue

We want to "remove" as many interval queries as possible, while ensuring that for each position i, the number of selected queries covering it, s(i), is at least the original array value nums[i], so that the value at that position can be reduced to 0 or below. If for some position i we cannot satisfy s(i) \ge nums[i], it means that no matter how many more queries we select, it is impossible to make that position zero, so we return -1.

To achieve this, we traverse the queries in order of their left endpoints and maintain:

  1. Difference array d: Used to record where the currently applied queries take effect—when we "apply" a query on the interval [l, r], we immediately do d[l] += 1 and d[r+1] -= 1. This way, when traversing to index i, the prefix sum tells us how many queries cover i.
  2. Max heap pq: Stores the right endpoints of the current "candidate" interval queries (store as negative numbers to simulate a max heap in Python's min heap). Why choose the "latest ending" interval? Because it can cover farther positions. Our greedy strategy is: at each i, only pick the longest interval from the heap when necessary to increase coverage, so that more intervals are available for subsequent positions.

The specific steps are as follows:

  1. Sort queries by the left endpoint l in ascending order;
  2. Initialize the difference array d with length n+1 (to handle the decrement at r+1), and set the current coverage count s=0, heap pointer j=0;
  3. For i=0 to n-1:

    • First, add d[i] to s to update the current coverage count;
    • Push all queries [l, r] with left endpoint \le i into the max heap pq (store -r), and advance j;
    • While the current coverage s is less than the required value nums[i], and the heap is not empty, and the top interval in the heap still covers i (i.e., -pq[0] \ge i):

      1. Pop the top of the heap (the longest interval), which is equivalent to "applying" this query;
      2. Increment s by 1 and do d[r+1] -= 1 (so that after passing r, the coverage count automatically decreases);
    • Repeat the above steps until s \ge nums[i] or no more intervals can be selected;

    • If at this point s < nums[i], it means it is impossible to make position i zero, so return -1.
  4. After traversing all positions, the intervals remaining in the heap are those that were not popped, i.e., the queries that are truly retained (not used for the "zeroing" task). The heap size is the answer.

The time complexity is O(n + m times log m), and the space complexity is O(n + m), where n is the length of the array and m is the number of queries.

Code

Python

Java

C++

Go

TypeScript

Try this approach in the editor →

Complexity Comparison

ApproachComplexity
Difference Array Technique

Time Complexity: O(M * N), where N is the length of nums and M is the number of queries since we attempt each query removal.

Space Complexity: O(N) for the difference array.

Greedy with Priority Queue

Time Complexity: O(N log N) (due to the heap operations).

Space Complexity: O(N).

Greedy + Difference Array + Priority Queue

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Difference Array + HeapO((n + q) log q)O(n + q)When tracking active range effects efficiently with prefix sums
Greedy with Priority QueueO((n + q) log q)O(q)General case; interview-preferred approach using greedy selection

Video Solution

Zero Array Transformation III | How to detect topic | How to detect Data Structure | Leetcode 3362codestorywithMIK12,181 views views

Watch 9 more video solutions →

Frequently Asked Questions

Is Zero Array Transformation III easy or hard?
Zero Array Transformation III is rated Medium on LeetCode with an acceptance rate around 55%. The difficulty comes from recognizing the greedy strategy and efficiently managing overlapping range queries using a heap and prefix-sum style tracking.
Zero Array Transformation III Python/Java solution
Python and Java implementations typically use a priority queue (heap) along with sorted queries. Python uses heapq with negative values to simulate a max heap, while Java uses PriorityQueue with a custom comparator. Both follow the same greedy logic and run in O((n + q) log q) time.
How to solve Zero Array Transformation III in O(n)?
A strict O(n) solution is not practical because queries must be managed dynamically. The closest optimal approach is O((n + q) log q) using a greedy algorithm with a priority queue. The heap allows efficient selection of the query with the farthest right boundary when additional decrements are needed.
What is the best approach for Zero Array Transformation III?
The most efficient approach uses a greedy strategy with a priority queue. While scanning the array, push all queries starting before the current index into a max heap ordered by their right boundary. If more decrements are required at the current index, activate the query with the farthest reach. This ensures maximum coverage for future indices and runs in O((n + q) log q) time.
Is Zero Array Transformation III asked at Google/Amazon/Meta?
Problems combining greedy strategies, heaps, and range updates are common in interviews at companies like Google, Amazon, and Meta. While the exact problem may not always appear, the underlying techniques—priority queues and prefix sum range handling—are frequently tested.
What data structure is used in Zero Array Transformation III?
The core data structure is a max heap (priority queue) used to select the query with the largest right boundary. Many implementations also use a difference array or prefix sum structure to track active range updates efficiently.
What is the time complexity of Zero Array Transformation III?
The optimal solution runs in O((n + q) log q) time, where n is the array length and q is the number of queries. Sorting queries and heap operations dominate the complexity. Space usage is typically O(q) or O(n + q) depending on whether a difference array is used.

Ready to solve this problem?

Practice Zero Array Transformation III with our built-in code editor and test cases.

Practice on FleetCode