Make Array Elements Equal to Zero
EASYDescription
You are given an integer array nums.
Start by selecting a starting position curr such that nums[curr] == 0, and choose a movement direction of either left or right.
After that, you repeat the following process:
- If
curris out of the range[0, n - 1], this process ends. - If
nums[curr] == 0, move in the current direction by incrementingcurrif you are moving right, or decrementingcurrif you are moving left. - Else if
nums[curr] > 0:- Decrement
nums[curr]by 1. - Reverse your movement direction (left becomes right and vice versa).
- Take a step in your new direction.
- Decrement
A selection of the initial position curr and movement direction is considered valid if every element in nums becomes 0 by the end of the process.
Return the number of possible valid selections.
Example 1:
Input: nums = [1,0,2,0,3]
Output: 2
Explanation:
The only possible valid selections are the following:
- Choose
curr = 3, and a movement direction to the left.[1,0,2,0,3] -> [1,0,2,0,3] -> [1,0,1,0,3] -> [1,0,1,0,3] -> [1,0,1,0,2] -> [1,0,1,0,2] -> [1,0,0,0,2] -> [1,0,0,0,2] -> [1,0,0,0,1] -> [1,0,0,0,1] -> [1,0,0,0,1] -> [1,0,0,0,1] -> [0,0,0,0,1] -> [0,0,0,0,1] -> [0,0,0,0,1] -> [0,0,0,0,1] -> [0,0,0,0,0].
- Choose
curr = 3, and a movement direction to the right.[1,0,2,0,3] -> [1,0,2,0,3] -> [1,0,2,0,2] -> [1,0,2,0,2] -> [1,0,1,0,2] -> [1,0,1,0,2] -> [1,0,1,0,1] -> [1,0,1,0,1] -> [1,0,0,0,1] -> [1,0,0,0,1] -> [1,0,0,0,0] -> [1,0,0,0,0] -> [1,0,0,0,0] -> [1,0,0,0,0] -> [0,0,0,0,0].
Example 2:
Input: nums = [2,3,4,0,4,1,0]
Output: 0
Explanation:
There are no possible valid selections.
Constraints:
1 <= nums.length <= 1000 <= nums[i] <= 100- There is at least one element
iwherenums[i] == 0.
Approaches
Checkout 2 different approaches to solve Make Array Elements Equal to Zero. Click on different approaches to view the approach and algorithm in detail.
Optimized Simulation with TreeSet
The brute-force simulation can be slow because of the time spent traversing blocks of zeros one step at a time. We can optimize this by skipping over consecutive zeros in a single operation. A TreeSet is an effective data structure for this purpose, as it can maintain the sorted indices of non-zero elements and find the next one in a given direction in logarithmic time.
Algorithm
- The overall structure is the same as the brute-force approach: iterate through all
(start_position, start_direction)pairs. - For each simulation, instead of a simple array, use a
TreeSetto store the indices of all non-zero elements. This allows for efficient queries of the next non-zero index. - Initialize the simulation with a copy of
nums, theTreeSetof non-zero indices,curr, anddir. - Loop as long as
curris within bounds: a. Ifnums_copy[curr] > 0: i. Decrementnums_copy[curr]. ii. Ifnums_copy[curr]becomes 0, removecurrfrom theTreeSet. iii. Reverse direction and move:dir *= -1,curr += dir. b. Ifnums_copy[curr] == 0: i. Instead of moving one step at a time, find the next non-zero element in the current direction using theTreeSet. ii. If moving right (dir=1), find the smallest index in theTreeSetthat is greater thancurr. This is done viatreeSet.ceiling(curr + 1). iii. If moving left (dir=-1), find the largest index in theTreeSetthat is less thancurr. This is done viatreeSet.floor(curr - 1). iv. If a next non-zero index is found, jumpcurrto that index. Otherwise, jumpcurrout of bounds. - After the loop terminates, the selection is valid if and only if the
TreeSetof non-zero indices is empty.
In this approach, we enhance the simulation by maintaining a TreeSet of indices where the array value is positive. When the simulation is at a position curr with a value of 0, instead of moving one step, we query the TreeSet to find the index of the next non-zero element in the current direction. This allows us to jump over entire blocks of zeros instantly.
For a rightward movement, treeSet.ceiling(curr + 1) gives us the next non-zero index. For a leftward movement, treeSet.floor(curr - 1) provides the previous non-zero index. If no such index exists, it means we've moved past all remaining non-zero numbers in that direction, and we can jump curr out of bounds to terminate that path segment.
When a non-zero element at an index is decremented to zero, we must remove that index from the TreeSet. This keeps our set of non-zero indices up-to-date. This optimization significantly reduces the number of steps in the simulation, especially for sparse arrays with large blocks of zeros.
class Solution {
public int makeArrayElementsEqualtoZero(int[] nums) {
int n = nums.length;
java.util.List<Integer> zeroIndices = new java.util.ArrayList<>();
for (int i = 0; i < n; i++) {
if (nums[i] == 0) {
zeroIndices.add(i);
}
}
int validCount = 0;
for (int startIdx : zeroIndices) {
if (isSelectionValid(nums.clone(), startIdx, 1)) {
validCount++;
}
if (isSelectionValid(nums.clone(), startIdx, -1)) {
validCount++;
}
}
return validCount;
}
private boolean isSelectionValid(int[] currentNums, int startCurr, int startDir) {
int n = currentNums.length;
java.util.TreeSet<Integer> nonZeroIndices = new java.util.TreeSet<>();
for (int i = 0; i < n; i++) {
if (currentNums[i] > 0) {
nonZeroIndices.add(i);
}
}
if (nonZeroIndices.isEmpty()) {
return true;
}
int curr = startCurr;
int dir = startDir;
while (curr >= 0 && curr < n) {
if (currentNums[curr] > 0) {
currentNums[curr]--;
if (currentNums[curr] == 0) {
nonZeroIndices.remove(curr);
}
dir *= -1;
curr += dir;
} else { // currentNums[curr] == 0
if (dir == 1) {
Integer nextNonZero = nonZeroIndices.ceiling(curr + 1);
curr = (nextNonZero != null) ? nextNonZero : n;
} else { // dir == -1
Integer prevNonZero = nonZeroIndices.floor(curr - 1);
curr = (prevNonZero != null) ? prevNonZero : -1;
}
}
}
return nonZeroIndices.isEmpty();
}
}
Complexity Analysis
Pros and Cons
- Significantly faster than the naive simulation, especially for sparse arrays.
- The time complexity is well within typical limits for competitive programming platforms.
- Slightly more complex to implement due to the use of a
TreeSet.
Code Solutions
Checking out 3 solutions in different languages for Make Array Elements Equal to Zero. Click on different languages to view the code.
class Solution {
public
int countValidSelections(int[] nums) {
int s = Arrays.stream(nums).sum();
int ans = 0, l = 0;
for (int x : nums) {
if (x != 0) {
l += x;
} else if (l * 2 == s) {
ans += 2;
} else if (Math.abs(l * 2 - s) <= 1) {
++ans;
}
}
return ans;
}
}
Video Solution
Watch the video walkthrough for Make Array Elements Equal to Zero
Similar Questions
5 related questions you might find useful
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.