The in-place manipulations that come up constantly and are easy to get wrong from memory.

Rotating an array by — the reversal trick

To rotate a[0..n-1] left by :

void rotateLeft(vector<int>& a, int k) {
    int n = a.size(); k = ((k % n) + n) % n;
    reverse(a.begin(), a.begin() + k);
    reverse(a.begin() + k, a.end());
    reverse(a.begin(), a.end());
}

time, extra space. To rotate right by , reverse the whole array first, then the two parts:

DirectionSequence
Left by reverse first → reverse rest → reverse all
Right by reverse all → reverse first → reverse rest

Why it works: reversing gives ; reversing each part first means the final reversal lands them as . The identity is the whole proof.

The ((k % n) + n) % n guard handles and negative — both are common in problems and both silently break the naive version.

The cycle-following alternative

The juggling algorithm rotates in place by walking cycles:

for (int s = 0; s < gcd(n, k); s++) {
    int cur = s, val = a[s];
    do {
        int nxt = (cur + k) % n;
        swap(val, a[nxt]);
        cur = nxt;
    } while (cur != s);
}

Same complexity, one pass instead of three, but far worse cache behaviour — the reversal method is usually faster in practice despite doing more total work. See cycle following for the same idea in another setting.

Matrix transformations

All of these are compositions of transpose and reverse:

TransformationRecipe
Rotate 90° clockwisetranspose, then reverse each row
Rotate 90° counter-clockwisetranspose, then reverse each column (i.e. reverse the row order)
Rotate 180°reverse row order and reverse each row
Horizontal flip (top ↔ bottom)reverse the row order
Vertical flip (left ↔ right)reverse each row
Main-diagonal mirrortranspose
Anti-diagonal mirrorreverse rows → transpose → reverse rows
void rotate90(vector<vector<int>>& m) {
    int n = m.size();
    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++) swap(m[i][j], m[j][i]);   // transpose
    for (auto& row : m) reverse(row.begin(), row.end());          // reverse rows
}

Derive, don't memorise

Rotate the corner in your head and see where it lands. Transpose sends ; reversing rows sends . Composing gives , which is exactly clockwise rotation. Two seconds of checking beats a memorised table you might have backwards.

Note j = i + 1 in the transpose loop: starting at j = 0 swaps every pair twice, leaving the matrix unchanged. That is one of the most common off-by-one bugs in this code.

Non-square matrices

The in-place trick only works for square matrices. An matrix rotates into a one, so allocate:

vector<vector<int>> rotate90(const vector<vector<int>>& m) {
    int r = m.size(), c = m[0].size();
    vector<vector<int>> res(c, vector<int>(r));
    for (int i = 0; i < r; i++)
        for (int j = 0; j < c; j++) res[j][r - 1 - i] = m[i][j];
    return res;
}

Other in-place array patterns

TaskTechnique
Remove duplicates from a sorted arraytwo pointers: unique(all(a))
Partition by a predicateDutch national flag
Move zeros to the enda write pointer trailing a read pointer
Reverse in groups of repeated reverse on subranges
Next lexicographic permutationnext_permutation, or the suffix-scan derivation
Find the missing number in XOR everything, or sum and subtract
Find a duplicate without extra spaceFloyd’s cycle detection on the index graph
Apply a permutation in placewalk its cycles

Traversal orders worth having ready

// spiral traversal
int top = 0, bot = r - 1, lef = 0, rig = c - 1;
while (top <= bot && lef <= rig) {
    for (int j = lef; j <= rig; j++) out.push_back(m[top][j]); top++;
    for (int i = top; i <= bot; i++) out.push_back(m[i][rig]); rig--;
    if (top <= bot) { for (int j = rig; j >= lef; j--) out.push_back(m[bot][j]); bot--; }
    if (lef <= rig) { for (int i = bot; i >= top; i--) out.push_back(m[i][lef]); lef++; }
}

The two guards before the third and fourth loops are essential: without them a single remaining row or column is emitted twice.

Diagonals are indexed by i + j (anti-diagonals, to ) and by i - j + c - 1 (main diagonals) — a fact that turns many grid DP problems into a one-dimensional sweep.

See also: Prefix Sums · Two Pointers · Sorting · Vectors and Rotations