Remove every occurrence of val from nums in place, and return how many
elements are left. What sits beyond that count does not matter.
nums := []int{3, 2, 2, 3}k := removeElement(nums, 3) // k = 2, nums starts [2 2 …]Why not just delete
Deleting from the middle of an array means shifting everything after it down one
slot. Do that for each removal and you have on an input that is mostly
val.
The trick is that the problem never asked you to delete. It asked for the survivors to be at the front and for a count.
One boundary
Keep an index k marking the end of the kept prefix. Scan with i. Whenever
nums[i] is a keeper, put it at k and advance the boundary.
remove every 3
green = the kept prefix · everything from k onward is scratch
3 is what we are removing — skip it. Only i moves, so the boundary stays where it is and this value ends up behind it.
func removeElement(nums []int, val int) int { var pointer = 0
for i := 0; i < len(nums); i++ { if nums[i] != val { nums[i], nums[pointer] = nums[pointer], nums[i] pointer++ } }
return pointer}One pass, time, space.
Swap or assign?
The version above swaps. The more common version just overwrites:
if nums[i] != val { nums[pointer] = nums[i] pointer++}Both are correct here, and they differ in what they leave behind. Assigning overwrites the tail with copies; swapping preserves every original element, just reordered — the discarded values end up after the boundary rather than being lost.
For this problem the tail is explicitly ignored, so it makes no difference. Swapping costs one extra write per keeper and buys a property you were not asked for; assigning is the leaner default. Reach for the swap when the tail is also an answer — as in Dutch-national-flag partitioning, or in quickselect, where both sides matter.
In-place means the caller’s array changes
This function mutates the slice it was handed, and the caller sees it. Here that is the whole point — the problem says in place — but it is worth being explicit, because a Go slice parameter looks like a value and is not.
nums := []int{3, 2, 2, 3}k := removeElement(nums, 3)fmt.Println(nums) // [2 2 3 3] — reorderedfmt.Println(nums[:k]) // [2 2] — the answerA function that reorders its argument should say so in its name or its doc comment. See concatenation of array for the version of this that bites when you did not intend it.
The pattern
This is the smallest instance of partition by predicate, and once you see it the family is large:
- Move zeroes — same loop,
valis 0, and the assign version needs a second pass to zero the tail. - Remove duplicates from a sorted array — the predicate compares against the previous keeper instead of a constant.
- Sort colors — three regions instead of two, which needs a third pointer.
The invariant is the same in all of them; only the test changes.