Dev Skills

Reverse and rotate a slice in place

Two pointers, the three-reversal trick, and the slice aliasing that makes "in place" mean what it says.

Topic 25 of 98 · 5 min to read · 55 min to build
After this topic you can
  • Write in-place reverse and rotate with two pointers and three reversals.
  • Predict how reversing a sub-slice changes the original slice.
  • Fix the divide-by-zero panic on an empty slice.

The problem

Reverse a slice in place. Then rotate it right by k positions — [1 2 3 4 5 6 7] rotated by 3 is [5 6 7 1 2 3 4] — using O(1) extra space.

Brute force first

Rotate right by 1, k times: save the last element, shift everything one place right, put the saved one at the front. Or copy into a new slice at (i+k) % n.

Shifting is O(n·k) time, O(1) space. The copy is O(n) time but O(n) extra space, which breaks the "in place" rule.

The approach

Reverse: two indices, one from each end, swap and move inwards. Go’s tuple assignment s[i], s[j] = s[j], s[i] needs no temporary.

Rotate: reverse the whole slice, then reverse the first k, then the rest. Each element moves a constant number of times: O(n) time, O(1) space. Taking k %= len(s) first handles k bigger than the length.

rotate.go
package main
import (
"fmt"
"slices"
)
// reverse swaps from both ends towards the middle. In place, O(1) extra space.
func reverse(s []int) {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
// rotateRight by k using three reversals: whole, first k, rest.
func rotateRight(s []int, k int) {
if len(s) == 0 {
return
}
k %= len(s) // k may be larger than len
reverse(s)
reverse(s[:k])
reverse(s[k:])
}
func main() {
a := []int{1, 2, 3, 4, 5}
reverse(a)
fmt.Println(a) // [5 4 3 2 1]
b := []int{1, 2, 3, 4, 5, 6, 7}
rotateRight(b, 3)
fmt.Println(b) // [5 6 7 1 2 3 4]
// The stdlib already has reverse. Use it unless they ask you to write it.
c := []int{1, 2, 3}
slices.Reverse(c)
fmt.Println(c) // [3 2 1]
// The aliasing trap: a sub-slice shares the array, so the caller sees this.
d := []int{1, 2, 3, 4}
reverse(d[:2])
fmt.Println(d) // [2 1 3 4]
// Reversing a string: convert to runes, not bytes, or UTF-8 breaks.
r := []rune("héllo")
slices.Reverse(r)
fmt.Println(string(r)) // olléh
}

Dry run

Rotate [1 2 3 4 5 6 7] right by k = 3 with three reversals:

stepwhat you reverseslice after
0(start)[1 2 3 4 5 6 7]
1whole slice[7 6 5 4 3 2 1]
2first k = 3[5 6 7 4 3 2 1]
3the rest (index 3 onwards)[5 6 7 1 2 3 4]

Go-specific gotchas

  • A slice is a view, not a copy. reverse(s[:k]) changes the caller’s array, which is exactly why the three-reversal trick works without returning anything. It is also why passing a sub-slice to a function you did not write can surprise you.
  • Need a copy? slices.Clone(s). Assigning t := s copies only the header.
  • Strings are immutable. To reverse one, convert to []rune, not []byte. Reversing bytes splits multi-byte UTF-8 characters and prints garbage.
  • Guard the empty slice before k %= len(s), or you divide by zero and panic.
The short version
  • Two pointers from the ends for reverse; three reversals for rotate.
  • Sub-slices share the backing array, so in-place really is in place.
  • slices.Reverse exists — use it unless they ask you to write it.
Remember: A slice header is three words. Copying it never copies the elements.
Build this before moving on
Rotate left by k with the same trick, and write a table test with k = 0, k = len, and k > len.
Coding challenge · checked by tests
Write rotateRight(s []int, k int) that rotates s right by k positions in place, with no extra slice (the hidden tests check that it allocates nothing). k may be 0 or bigger than len(s), and s may be empty. Example: [1 2 3 4 5 6 7], k = 3 → [5 6 7 1 2 3 4].

Tab indents. Press Esc, then Tab, to leave the editor.

Then try these in your own editor
  1. 1The main task: Rotate left by k with the same trick, and write a table test with k = 0, k = len, and k > len.
  2. 2Predict the output: a := []int{1,2,3,4}; b := a[1:3]; slices.Reverse(b); fmt.Println(a).
  3. 3Reverse the words in a sentence ("the sky is blue" → "blue is sky the") with strings.Fields, slices.Reverse and strings.Join.
  4. 4Dry run the three-reversal rotate on [1 2 3 4 5] with k = 7. What is k after k %= len(s), and what is the result?
  5. 5Check whether a string is a palindrome using two pointers, so that "नमन" and "madam" both work.
Official documentation
Check yourselfTake the Go for coding rounds test