A slow write pointer keeps the last unique value while a fast reader scans ahead. Because the array is sorted, duplicates are always adjacent.
Compact a **sorted** array in place so each value appears once, and return `k`, the new logical length. A fast `read` pointer scans every slot; a slow `write` pointer marks where the next unique value belongs. Because the array is sorted, duplicates are always adjacent, so a single comparison against `nums[write - 1]` is enough to recognise one.
In an unsorted array you would need a hash set to know whether a value has been seen. Sorted, every copy of a value sits in one contiguous run, so the only value you can possibly be a duplicate of is the last unique one you kept, `nums[write - 1]`. One comparison, no extra memory.
`write` starts at 1 because `nums[0]` is unique by definition. read=1 sees 1 === nums[0] → skip. read=2 sees 2 ≠ 1 → copy into slot 1, write=2. read=3 sees 2 === nums[1] → skip. read=4 sees 3 → copy into slot 2, write=3. read=5 sees 4 → copy into slot 3, write=4. read=6 sees 4 === nums[3] → skip. Return k = 4.
The array ends as [1, 2, 3, 4, 3, 4, 4] and that is the correct answer. Nothing is deleted; the caller is told to read only `nums[0..k)`. Everything from index `k` onwards is whatever happened to be left behind, and comparing it against an expected output is the single most common way people convince themselves this solution is broken.
When `read === write` the value is copied onto itself. That is a no-op, and exactly why no "is it already in place?" branch is needed. When `read > write`, slot `write` holds a value `read` has already walked past, so overwriting it destroys nothing that is still needed. Order survives because unique values are written in the order they are met.
One pass, one comparison and at most one assignment per index, so the time is O(n). Both pointers are plain integers and the array is rewritten in place, so the extra space is O(1).
Change the comparison to `nums[read] !== nums[write - 2]` and the same loop solves "at most two duplicates allowed". The write pointer is just a cursor over an output you are building inside the input. The same read/write partition powers move zeroes, remove element, and partitioning around a pivot.