| title | 🔄 Move All Zeroes to End | GFG Solution 🎯 | |||||||
|---|---|---|---|---|---|---|---|---|
| keywords🏷️ |
|
|||||||
| author | ✍️ Het Patel (Hunterdii) | |||||||
| description | ✅ GFG solution to Move All Zeroes to End: rearrange array by moving zeros to end while maintaining order using efficient two-pointer technique. 🚀 | |||||||
| date | 📅 2025-03-01 |
The problem can be found at the following link: 🔗 Question Link
You are given an array arr[] of non-negative integers. You have to move all the zeros in the array to the right end while maintaining the relative order of the non-zero elements. The operation must be performed in place, meaning you should not use extra space for another array.
Input: arr[] = [1, 2, 0, 4, 3, 0, 5, 0]
Output: [1, 2, 4, 3, 5, 0, 0, 0]
Explanation: There are three 0s that are moved to the end while maintaining
the relative order of non-zero elements.Input: arr[] = [10, 20, 30]
Output: [10, 20, 30]
Explanation: No change in array as there are no 0s.Input: arr[] = [0, 0]
Output: [0, 0]
Explanation: No change in array as there are all 0s.$1 \le \text{arr.size()} \le 10^5$ $0 \le \text{arr}[i] \le 10^5$
The optimal solution uses Two-Pointer In-Place Rearrangement:
-
Key Insight:
- Use a pointer to track the position where the next non-zero element should be placed.
- Traverse the array and move non-zero elements to their correct positions.
- This automatically pushes zeros to the end.
-
Position Tracking:
- Maintain a
pospointer starting at index 0. - This pointer always points to the next position for a non-zero element.
- When we find a non-zero element, place it at
posand incrementpos.
- Maintain a
-
In-Place Operation:
- Simply copy non-zero elements to positions 0, 1, 2, ...
- After all non-zeros are placed, fill remaining positions with zeros.
- This maintains relative order and works in-place.
-
Algorithm Steps:
- Iterate through array with index
i. - If
arr[i] != 0, copy it toarr[pos]and incrementpos. - After loop, fill
arr[pos]toarr[n-1]with zeros. - Return the modified array.
- Iterate through array with index
Why This Works: By copying non-zeros to the front sequentially, we preserve their order. Filling remaining positions with zeros pushes all zeros to the end.
- Expected Time Complexity: O(n), where n is the size of the array. We make a single pass to move non-zero elements, and another pass to fill zeros in the remaining positions, resulting in linear time.
- Expected Auxiliary Space Complexity: O(1), as we perform the rearrangement in-place using only a constant amount of extra space for pointer variables.
class Solution {
public:
void pushZerosToEnd(vector<int>& arr) {
int pos = 0;
for (int i = 0; i < arr.size(); i++)
if (arr[i] != 0) arr[pos++] = arr[i];
while (pos < arr.size()) arr[pos++] = 0;
}
};⚡ View Alternative Approaches with Code and Analysis
- Use a pointer to track position for next non-zero element.
- When non-zero element found, swap with element at tracked position.
- Increment position pointer after each swap.
- This preserves order and moves zeros to end in single pass.
class Solution {
public:
void pushZerosToEnd(vector<int>& arr) {
int count = 0;
for (int i = 0; i < arr.size(); i++) {
if (arr[i] != 0) {
swap(arr[i], arr[count]);
count++;
}
}
}
};- Time: ⏱️ O(n) - Single pass with swaps
- Auxiliary Space: 💾 O(1) - In-place with constant space
- Single pass solution
- Uses swap instead of copy + fill
- Elegant and widely used approach
- Use stable partition to separate non-zeros and zeros.
- Maintain relative order during partitioning.
- All non-zeros move to front, zeros to end.
- STL stable_partition maintains element order.
class Solution {
public:
void pushZerosToEnd(vector<int>& arr) {
stable_partition(arr.begin(), arr.end(), [](int x) { return x != 0; });
}
};- Time: ⏱️ O(n) - Linear partitioning
- Auxiliary Space: 💾 O(1) - In-place partition
- One-liner solution using STL
- Clean and concise
- Maintains stability automatically
- Count number of non-zero elements.
- Create temporary storage for non-zeros.
- Fill original array with non-zeros first, then zeros.
- Two-pass solution with explicit separation.
class Solution {
public:
void pushZerosToEnd(vector<int>& arr) {
int n = arr.size();
vector<int> temp;
for (int x : arr)
if (x != 0) temp.push_back(x);
for (int i = 0; i < temp.size(); i++)
arr[i] = temp[i];
for (int i = temp.size(); i < n; i++)
arr[i] = 0;
}
};- Time: ⏱️ O(n) - Linear time with multiple passes
- Auxiliary Space: 💾 O(n) - Temporary array for non-zeros
- Very clear and easy to understand
- Good for educational purposes
- Explicit separation of concerns
| 🚀 Approach | ⏱️ Time Complexity | 💾 Space Complexity | ✅ Pros | |
|---|---|---|---|---|
| 🎯 Copy + Fill | 🟢 O(n) | 🟢 O(1) | 🚀 Simple two-pass solution | 🔧 Two passes required |
| 🔄 Swap-Based | 🟢 O(n) | 🟢 O(1) | ⚡ Single pass with swaps | 🔧 Swap overhead |
| 📊 Stable Partition | 🟢 O(n) | 🟢 O(1) | 🎯 One-liner, clean | 🔧 STL dependency |
| 📈 Count and Fill | 🟢 O(n) | 🔴 O(n) | 📖 Very clear logic | 💾 Extra space required |
| 🎯 Scenario | 🎖️ Recommended Approach | 🔥 Performance Rating |
|---|---|---|
| 🏅 Optimal performance needed | 🥇 Swap-Based | ★★★★★ |
| 📖 Readability priority | 🥈 Copy + Fill | ★★★★★ |
| 🔧 Shortest code | 🥉 Stable Partition | ★★★★☆ |
| 🎯 Learning purposes | 🏅 Count and Fill | ★★★★☆ |
class Solution {
void pushZerosToEnd(int[] arr) {
int pos = 0;
for (int i = 0; i < arr.length; i++)
if (arr[i] != 0) arr[pos++] = arr[i];
while (pos < arr.length) arr[pos++] = 0;
}
}class Solution:
def pushZerosToEnd(self, arr):
pos = 0
for i in range(len(arr)):
if arr[i] != 0:
arr[pos] = arr[i]
pos += 1
while pos < len(arr):
arr[pos] = 0
pos += 1For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: 📬 Any Questions?. Let's make this learning journey more collaborative!
⭐ If you find this helpful, please give this repository a star! ⭐