Math & Geometry
A toolkit of number-theory and coordinate-geometry tricks - digit peeling, gcd, counting prime factors, squared distances, cross products and normalised slopes - that replaces brute force with exact integer math.
Instinct Digits, factors, slopes or distances hide a formula - find the invariant, then guard against overflow, negatives and floating-point error.
Memory hack Mod peels, gcd reduces, squares compare - and long saves the day. Peel digits with %10, reduce slopes with gcd, compare squared distances.
At a glance
When to use it
- The problem works on the digits of a number, its factors, or a formula like pow, gcd or modulo
- You must stay within 32-bit range or return 0 on overflow
- Points in the plane must be checked for distances, shapes, slopes or collinearity
- A brute force would build huge numbers like n! or compare floating-point values
Key idea
Find the invariant (a digit pattern, a count of prime factors, a reduced slope, a shared midpoint) and do exact integer arithmetic on it; this avoids huge intermediates and float errors and usually cuts the work to O(log n) for numbers or O(n^2) for point sets.
Typical complexity
O(log n) time for digit or factor work, O(n^2) for point pairs, O(1) to O(n) space
| # | Common problems | Level | Our solution | Practice |
|---|---|---|---|---|
| 1 | Palindrome Number | Easy | Read solution | LeetCode ↗ |
| 2 | Reverse Integer | Medium | Read solution | LeetCode ↗ |
| 3 | Factorial Trailing Zeroes | Medium | Read solution | LeetCode ↗ |
| 4 | Valid Square | Medium | Read solution | LeetCode ↗ |
| 5 | Minimum Area Rectangle II | Medium | Read solution | LeetCode ↗ |
| 6 | Max Points on a Line | Hard | Read solution | LeetCode ↗ |
The instinct
These problems look like puzzles but are usually one observation plus careful arithmetic. The observation is a property that survives the operations (a digit pattern, a count of prime factors, a slope, a midpoint). The arithmetic is where candidates lose points: 32-bit overflow, Java's negative remainders, and floating-point keys. The winning habit is to stay in integers for as long as possible: compare squared distances, store slopes as reduced fractions, and check overflow before multiplying.
Recognise it
| Signal in the problem | Why it points here |
|---|---|
| "Reverse the digits", "is it a palindrome without converting to string" (Reverse Integer, Palindrome Number) | Peel digits with % 10 and / 10, check overflow each step |
| "Assume a 32-bit signed environment", "return 0 on overflow" | The test is your overflow guard, not the loop |
| "Number of trailing zeros in n!" (Factorial Trailing Zeroes) | Count factors of 5 instead of computing n! |
| "Do these 4 points form a square?" (Valid Square) | Squared pairwise distances; no square roots |
| "Maximum number of points on the same line" (Max Points on a Line) | Normalised slope as a hash key from each anchor point |
| "Minimum area rectangle, sides not necessarily axis-parallel" (Minimum Area Rectangle II) | Diagonals share a midpoint and length - group pairs by that |
| "Pow, sqrt, gcd, lcm, prime, modulo 1e9+7" | Fast exponentiation, binary search on the answer, Euclid, sieve |
Not this pattern if...
- The "math" is really counting arrangements with overlapping subproblems - that is DP or combinatorics.
- Points are only used as graph nodes (e.g. Min Cost to Connect All Points) - it is MST / graph.
- You need the k closest points - squared distance helps, but the pattern is a heap or quickselect.
Memory hack
Mod peels, gcd reduces, squares compare - and long saves the day.
- % 10 peels the last digit, / 10 drops it.
- gcd turns a slope dy/dx into a canonical fraction you can hash.
- Squared distances avoid sqrt and keep everything exact.
- When in doubt, widen to long before the multiply, not after.
Analogy: a carpenter measures twice and cuts once. Do the reasoning on paper (invariant), then do arithmetic only with exact tools (integers) - a floating-point ruler drifts.
Say it out loud in the interview:
- "What stays the same / what am I really counting?" (factors of 5, equal slopes, shared midpoints)
- "Can every value fit in int? Where could it overflow or go negative?"
- "Edge cases: zero, negatives,
Integer.MIN_VALUE, duplicate points, vertical lines."
How it works
Decide which tool from the problem's nouns:
flowchart TD
A["Read the nouns"] --> B{"Digits of a number?"}
B -->|"yes"| C["Peel with mod 10 and div 10, overflow check before multiply"]
B -->|"no"| D{"Divisibility, factorial, primes?"}
D -->|"yes"| E["Count prime factors, gcd or sieve; never build huge numbers"]
D -->|"no"| F{"Points in the plane?"}
F -->|"distances or shapes"| G["Squared distances, cross product, midpoints"]
F -->|"collinear"| H["Slope as reduced dy/dx key per anchor point"]
F -->|"no"| I["Look for a formula: sums, powers, binary search on answer"]
Two quick traces:
- Factorial Trailing Zeroes, n = 100: multiples of 5 contribute 20 fives, multiples of 25 contribute 4 more, 125 > 100 stops. Answer 24, without ever touching 100!.
- Max Points on a Line: from anchor (1,1), the points (2,2), (3,3) and (-1,-1) give
dy/dx= 1/1, 2/2, -2/-2, which all reduce (sign normalised) to "1/1", so they land in one bucket.
Java template
class MathKit { // Reverse digits, returning 0 if the result leaves 32-bit range. static int reverse(int x) { int r = 0; while (x != 0) { int digit = x % 10; // negative for negative x - that's fine here x /= 10; if (r > Integer.MAX_VALUE / 10 || (r == Integer.MAX_VALUE / 10 && digit > 7)) return 0; if (r < Integer.MIN_VALUE / 10 || (r == Integer.MIN_VALUE / 10 && digit < -8)) return 0; r = r * 10 + digit; } return r; } static int gcd(int a, int b) { return b == 0 ? Math.abs(a) : gcd(b, a % b); } // base^exp % mod in O(log exp). static long powMod(long base, long exp, long mod) { long result = 1 % mod; base %= mod; if (base < 0) base += mod; // Java remainders can be negative while (exp > 0) { if ((exp & 1) == 1) result = result * base % mod; base = base * base % mod; exp >>= 1; } return result; } // Count of prime factor p in n! (p = 5 gives trailing zeros). static long factorInFactorial(long n, long p) { long count = 0; while (n > 0) { n /= p; count += n; } return count; } } class GeoKit { static long dist2(int[] a, int[] b) { long dx = a[0] - b[0], dy = a[1] - b[1]; return dx * dx + dy * dy; // exact, no sqrt } // > 0: o->a->b turns left, < 0: right, 0: collinear. static long cross(int[] o, int[] a, int[] b) { return (long) (a[0] - o[0]) * (b[1] - o[1]) - (long) (a[1] - o[1]) * (b[0] - o[0]); } // Canonical slope key between two distinct points. static String slopeKey(int[] a, int[] b) { int dx = b[0] - a[0], dy = b[1] - a[1]; if (dx == 0) return "inf"; // vertical line if (dy == 0) return "0"; // horizontal line int g = MathKit.gcd(dx, dy); dx /= g; dy /= g; if (dx < 0) { dx = -dx; dy = -dy; } // one sign convention return dy + "/" + dx; } }
Complexity
| Task | Time | Space |
|---|---|---|
| Digit peeling (reverse, palindrome) | O(number of digits) = O(log n) | O(1) |
| Factor counting in n! | O(log_p n) | O(1) |
| gcd / fast power | O(log n) | O(1) |
| Valid Square (6 pair distances) | O(1) | O(1) |
| Max Points on a Line (slope map per anchor) | O(n²) | O(n) |
| Minimum Area Rectangle II (group pairs by midpoint + length) | O(n²) pairs, plus pairs within each group | O(n²) |
Variations
- Digit manipulation - peel, rebuild, compare halves; reverse only half of the number to dodge overflow. Palindrome Number, Reverse Integer, Add Digits.
- Factor and divisor counting - count the limiting prime instead of forming the product. Factorial Trailing Zeroes, Count Primes (sieve).
- Fast operators - exponentiation by squaring, binary search for roots. Pow(x, n), Sqrt(x).
- Shape checks with distances - sort the 6 squared distances: 4 equal non-zero sides and 2 equal larger diagonals. Valid Square.
- Collinearity / slopes - reduced-fraction keys or cross product = 0. Max Points on a Line.
- Rectangles from diagonals - pairs with the same midpoint and length are diagonals of one rectangle. Minimum Area Rectangle II.
- Overlap tests - axis-aligned rectangles overlap when they overlap on both axes. Rectangle Overlap, Rectangle Area.
Common mistakes
Math.abs(Integer.MIN_VALUE)is still negative; widen tolongfirst or avoidabson raw input.- Java's
%keeps the sign of the dividend (-7 % 10 == -7); normalise with((x % m) + m) % mfor modular math. - Forgetting degenerate inputs: duplicate points in Valid Square (zero-length side), duplicate points in Max Points on a Line (they match every slope).
- Multiplying two
intcoordinates before casting -(long) (a * b)overflows first; write(long) a * b. - Computing a huge intermediate (n!, a^b) instead of counting factors or reducing modulo as you go.
Never use a double slope as a hash key. 0.0 and -0.0 are different keys, 1/3 is not exactly representable, and vertical lines give infinity. Store slopes as a reduced (dy, dx) pair with one sign convention.
All practice problems
6 problems on this site use this pattern, easiest first. Solve them in order and say the instinct out loud before you code.