Common Algorithmic Techniques: Array Indexing, Modulo, Two‑Pointer, Bit‑Shift, Sentinel Nodes, and Recursion Optimizations
This article introduces several practical algorithmic tricks—using array indices as counters, applying modulo for circular traversal, employing two‑pointer methods for linked‑list problems, leveraging bit‑shift and bitwise operations, adding sentinel nodes, and optimizing recursive solutions with memoization and bottom‑up DP—each illustrated with Java code examples.
Today we discuss frequently used algorithmic tricks that can help you write faster and cleaner code when solving interview problems.
1. Clever use of array indices – Treat the value of an element as an index to count occurrences in O(n) time, e.g., arr[a]++ while scanning a character array.
public void f(int arr[]) {
int[] temp = new int[21];
for (int i = 0; i < arr.length; i++) {
temp[arr[i]]++;
}
// sequential printing
for (int i = 0; i < 21; i++) {
for (int j = 0; j < temp[i]; j++) {
System.out.println(i);
}
}
}2. Clever use of modulo – Replace manual boundary checks in circular structures with pos = (pos + 1) % N to keep the index within range.
for (int i = 0; i < N; i++) {
// use arr[pos]
pos = (pos + 1) % N;
}3. Clever use of two pointers – Apply a slow and a fast pointer to detect cycles, find the middle node, or locate the k‑th node from the end in a singly linked list.
4. Clever use of bit‑shift operations – Replace divisions by powers of two with right shifts, e.g., n >> 1 for n / 2 , and use bitwise AND to test oddness: if ((n & 1) == 1) { … } .
if (n & 1 == 1) {
dosomething();
}5. Sentinel nodes – Add a dummy head (or an array sentinel) to simplify edge‑case handling when inserting or deleting at the beginning of a list or array.
6. Recursion‑related optimizations
(1) State saving (memoization) – Cache intermediate results to avoid repeated work, as shown in the Fibonacci‑like problem.
int[] memo = new int[1000];
public int f(int n) {
if (n <= 2) return n;
if (memo[n] != 0) return memo[n];
memo[n] = f(n-1) + f(n-2);
return memo[n];
}(2) Bottom‑up (iterative) DP – Build the solution from the base cases upward to eliminate deep recursion and reduce stack usage.
public int f(int n) {
if (n <= 2) return n;
int f1 = 1, f2 = 2, sum = 0;
for (int i = 3; i <= n; i++) {
sum = f1 + f2;
f1 = f2;
f2 = sum;
}
return sum;
}In summary, when solving algorithmic problems consider whether you can use array indexing, modulo arithmetic, two‑pointer techniques, bit operations, sentinel nodes, or recursion optimizations (memoization or bottom‑up DP) to improve efficiency and code simplicity.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.