Intuition
Before any of the clever part, handle the thing that breaks most submissions: k can exceed n. Rotating by n returns the array to itself, so without k %= n you either index out of bounds or grind through pointless work. Once that is out of the way, the reversal algorithm is the trick worth memorising — reverse the whole array, then the first k, then the rest. The full reverse puts the right block in front but backwards; the two local reversals straighten each one out. Three linear passes, O(1) space, no temporary array.
Approach
Reduce k first
Rotating by n returns the array to itself, so take k %= n. Skipping this either indexes out of bounds or does needless work, and it is the most common bug in the reversal version. If k becomes 0, there is nothing to do.
Reverse the whole array
After a full reverse, the block that should end up at the front is at the front — but reversed — and the block that should follow is behind it, also reversed. The relative arrangement of the two blocks is now correct even though their internal orders are not.
Reverse each block back
Reverse [0, k) and then [k, n). Each block returns to its original internal order while staying in its new position, and the result is the rotation. Three passes of O(n) each and two index variables, versus the O(n) extra space of the copy-to-a-new-array approach.
Solution & live demo
Edge cases
Nothing changes — worth an early return.
The modulus reduces it; forgetting it causes an out-of-bounds slice.
The modulus makes it 0, so the array is unchanged.
Any rotation is a no-op.