Zero Array Transformation III - Solution & Explanation
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]innumsby 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], decrementnums[0]andnums[2]by 1 andnums[1]by 0. - Using
queries[1], decrementnums[0]andnums[2]by 1 andnums[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 <= 1050 <= nums[i] <= 1051 <= queries.length <= 105queries[i].length == 20 <= 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.
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).
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:
- 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 dod[l] += 1andd[r+1] -= 1. This way, when traversing to indexi, the prefix sum tells us how many queries coveri. - 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 eachi, 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:
- Sort
queriesby the left endpointlin ascending order; - Initialize the difference array
dwith lengthn+1(to handle the decrement atr+1), and set the current coverage counts=0, heap pointerj=0; -
For
i=0ton-1:- First, add
d[i]tosto update the current coverage count; - Push all queries
[l, r]with left endpoint\le iinto the max heappq(store-r), and advancej; -
While the current coverage
sis less than the required valuenums[i], and the heap is not empty, and the top interval in the heap still coversi(i.e.,-pq[0] \ge i):- Pop the top of the heap (the longest interval), which is equivalent to "applying" this query;
- Increment
sby 1 and dod[r+1] -= 1(so that after passingr, 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 positionizero, so return-1.
- First, add
-
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
Complexity Comparison
| Approach | Complexity |
|---|---|
| Difference Array Technique | Time Complexity: Space Complexity: |
| Greedy with Priority Queue | Time Complexity: Space Complexity: |
| Greedy + Difference Array + Priority Queue | — |
Detailed Complexity Analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Difference Array + Heap | O((n + q) log q) | O(n + q) | When tracking active range effects efficiently with prefix sums |
| Greedy with Priority Queue | O((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 3362 • codestorywithMIK • 12,181 views views
Watch 9 more video solutions →Frequently Asked Questions
Is Zero Array Transformation III easy or hard?
Zero Array Transformation III Python/Java solution
How to solve Zero Array Transformation III in O(n)?
What is the best approach for Zero Array Transformation III?
Is Zero Array Transformation III asked at Google/Amazon/Meta?
What data structure is used in Zero Array Transformation III?
What is the time complexity of Zero Array Transformation III?
Ready to solve this problem?
Practice Zero Array Transformation III with our built-in code editor and test cases.
Practice on FleetCode