Given an integer array nums, move all 0's to the end of it while maintaining the relative order of the non-zero elements.
Note that you must do this in-place without making a copy of the array.
Example 1:
Input: nums = [0,1,0,3,12] Output: [1,3,12,0,0]
Example 2:
Input: nums = [0] Output: [0]
Constraints:
1 <= nums.length <= 104-231 <= nums[i] <= 231 - 1When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The problem asks us to rearrange a collection of numbers so that all the non-zero numbers come first, followed by all the zeroes. The brute force approach involves considering every single possible arrangement of the numbers and picking the one that satisfies the condition.
Here's how the algorithm would work step-by-step:
import itertoolsdef move_zeroes_brute_force(list_of_numbers): # Generating all possible permutations is necessary to explore every ordering. for permutation_tuple in itertools.permutations(list_of_numbers): permutation_list = list(permutation_tuple) # We need to verify if the current arrangement satisfies the condition of non-zeroes first. found_zero = False is_valid_arrangement = True for number in permutation_list: if number == 0: found_zero = True elif found_zero: # This condition ensures that once a zero is encountered, no non-zero can appear after it. is_valid_arrangement = False break # If the arrangement meets the criteria, it's a valid solution and we can return it. if is_valid_arrangement: return permutation_list # In the rare case no valid arrangement is found (e.g., if the input is empty), return an empty list. return []The most efficient way to solve this is by rearranging the existing items in place, treating it like a careful sorting process. We'll manage two conceptual points: one that keeps track of where the next non-zero item should go, and another that scans through all the items.
Here's how the algorithm would work step-by-step:
def move_zeroes(list_of_numbers): next_non_zero_position_index = 0 # This index marks where the next non-zero element should be placed. for current_scan_index in range(len(list_of_numbers)): # If the current element is not zero, move it to the next non-zero position. if list_of_numbers[current_scan_index] != 0: list_of_numbers[next_non_zero_position_index] = list_of_numbers[current_scan_index] next_non_zero_position_index += 1 # Fill the remaining positions from the next non-zero position to the end with zeroes. # This ensures all zeroes are at the end of the list. while next_non_zero_position_index < len(list_of_numbers): list_of_numbers[next_non_zero_position_index] = 0 next_non_zero_position_index += 1| Case | How to Handle |
|---|---|
| Null or empty input array | The function should gracefully handle null or empty arrays by doing nothing and returning immediately. |
| Array with a single element | An array with one element, whether zero or non-zero, requires no modification and should be returned as is. |
| Array with all zeros | If the array consists entirely of zeros, no elements need to be moved, and the array remains unchanged. |
| Array with no zeros | If the array contains no zeros, the relative order of non-zero elements is preserved, and no actual movement occurs. |
| Array with only one non-zero element | The single non-zero element should remain in its original relative position, followed by all the zeros. |
| Array with negative numbers and zeros | The algorithm should correctly distinguish between zero and negative non-zero numbers, maintaining their relative order. |
| Very large input array | The chosen in-place algorithm, typically using a two-pointer approach, has a time complexity of O(n) and space complexity of O(1), which scales efficiently for large inputs. |
| Array with maximum and minimum integer values | The algorithm should not be affected by the magnitude of the integer values as it only compares them to zero. |