Where it runs
1. The problem
You get a big array (a numbered list of boxes) and you have to rearrange it. You might reverse it, push all the zeros to the end, or take some items out. The easy way is to make a new array and fill it. That works, but it uses twice the memory: for a while the old array and the new one both sit in memory.
Sometimes that is fine. Sometimes the array is huge, or the program reuses it thousands of times a second, and there is no memory for a second copy. Then you change the array you already have and use only a couple of extra variables. That is an in-place change: you edit the same array and never make a new one.
2. In plain words
Take the first test, [0, 1, 0, 3]. The answer has to be [1, 3, 0, 0], and you may not build a second array to get there.
So you work inside the same four boxes. One marker, write, remembers which box gets the next number you keep. It starts at box 0. A second marker, read, looks at the boxes one by one from the left. When read finds a number that is not 0, you copy it into box write and move write one box to the right. The 1 lands in box 0, the 3 lands in box 1. Boxes 2 and 3 are then set to 0. The same four boxes now hold [1, 3, 0, 0], and no extra memory was needed. Saving that memory is the reason for the whole lesson.
3. The idea
"In place" means you edit the original boxes directly and spend almost no extra memory. Two moves solve most of these problems. Both use a pointer: a variable that holds a box number.
Two pointers from the ends (to reverse an array or swap items). Pointer lo starts at the first box, pointer hi at the last. Swap the two boxes they point at. Then move each one a step toward the other. Stop when they meet.
A write pointer (to move or remove items). A slow pointer write remembers where the next kept item goes. A fast pointer read walks the whole array. Each time read finds an item to keep, copy it into box write and move write one step forward.
Trace "zeros to the end" on [0, 1, 0, 3]. Read 0: skip it. Read 1: keep it, write it into box 0. The array is now [1, 1, 0, 3] and write is 1. Read 0: skip it. Read 3: keep it, write it into box 1. The array is now [1, 3, 0, 3] and write is 2. The kept numbers already stand at the front. Boxes 2 and 3 still hold old values, so fill them with zeros: [1, 3, 0, 0]. Done, with no second array.
4. What it costs
Time is O(n): one walk over the array. Space is O(1): a couple of variables for the indices and one spare box for a swap. None of these grow with the array. A new array would cost O(n) extra memory, and here you may not spend it.
One catch in JavaScript: you cannot change a string in place. So these problems give you an array of characters instead (one letter per box). You edit the array, and the string stays as it was.
5. Where this shows up
Before a program saves its log (the file where it writes down events), it removes private data from it. It does that without copying a big buffer (a stretch of memory that holds data). An input buffer gets cleaned up in place. A message gets packed into a network buffer of fixed size. A ring buffer gets maintained: a buffer of fixed size that fills up in a circle. In all of these, memory is tight or the same buffer is reused for every request. A fresh copy is wasted work there, and the write pointer lets you skip it.
inPlaceTransform([0, 4, 0, 0, 7, 2, 0, 5]) // shouldKeep = x => x !== 0write
Remove every 0 without a second array. read looks at each slot, write marks where the next kept value goes.
Bars: the numbers; a 0 has no bar. Both lanes keep the other numbers in their order.
One operation is one comparison or one write. Every frame, each lane does the same number of operations, so the slow one falls behind.
O(n²)O(n)
Operations for n numbers, and roughly how long they take at 100 million simple operations a second. An estimate from the same count, not a measurement.
Recognise it
Say these words and it is this pattern
- modify the array in place
- O(1) extra space
- do not allocate another array/string
- reverse/rotate/partition/move elements over a single buffer
- return the new length after removing duplicates
Looks similar, isn't
- Two pointers (same direction)
A slow and fast pair is one mechanic that rewrites a buffer. Working in place is the goal, not the mechanic.
- Hash set / map
A set drops duplicates in one pass but stores every key. In-place work exists to avoid that memory.
- Elementary sorts (selection, bubble, insertion)
Insertion sort also rewrites one buffer, but it reorders values. Here the surviving order never changes.
- Prefix sums
Prefix sums build a second array of running totals. That second array is the thing being avoided.
n up to 1e6 with a single pass gives O(n) time. Space stays O(1) because nothing new is allocated.
On LeetCode
Problems that ask you to rearrange, filter or reverse an array in place, with O(1) extra memory. Watch for the words "in-place" and "do not allocate extra space" in the statement.
This is the lesson task, so copy the non-zeros forward with a write pointer and fill the tail with zeros.
The same write pointer, keeping every value that is not equal to val.
Swap the two ends and step both pointers inward until they meet.
Reverse the whole array, then the first k items and the rest, with the swap from both ends.
Your task (Tier 1)
Write the function moveZeroes(nums).
Move every 0 to the end of the list. Keep the other numbers in the order they had. Do not make a new list. Change this one.
- Input:
nums, a list of numbers. Example:[0, 1, 0, 3]. - Return: nothing. You only change
nums.
Steps:
- Make a counter
write = 0. It is the next free spot at the front of the list. - Go through the list from left to right. When a number is not
0, copy it tonums[write], then add 1 towrite. - At the end, put
0in every spot fromwriteto the end of the list.
Done when all tests pass:
[0, 1, 0, 3]->[1, 3, 0, 0][1, 2, 3]->[1, 2, 3](no zeros, nothing changes)[0, 0]->[0, 0](all zeros)[0]->[0](one number)[]->[](empty list, must not crash)
Practice
moveZeroes (or reverseInPlace)
moveZeroes(nums) -> void (mutates nums)
export function moveZeroes(nums) {
// Your code here. The task is described in the box above the editor.
}
Running as a guest
The tests run right here, no account needed. Your code is kept in this browser only. A free account keeps it on every device, marks the step done and shows where you are in the course.
Hint ladder
Stuck? Reveal one rung at a time, but try it yourself first.