InterviewKata
Pattern 22 of 24

Math & Bit Manipulation

Some problems look like they need a search or a DP, but a small observation about numbers turns them into a formula or a loop over 32 bits. This page collects the tricks that come up again and again: binary exponentiation, XOR cancelling, counting bits, sieves, divisors and gcd counting.

1. What is this pattern for?

A cashier asked for 230 doesn't multiply by 2 thirty times: they square 2 → 4 → 16 → 256 … five times. Math-and-bits problems are like that: the slow way is obvious, and one observation about how numbers are built (binary digits, prime factors, divisors) makes it instant.

The recurring tools:

2. How it works (bisected)

  1. Write the slow version (multiply n times, try every number, check every pair) and its cost.
  2. Look at the structure of the numbers: their binary digits, their prime factors, their divisors, their parity.
  3. Find the invariant that the slow version is secretly computing: "pairs cancel under XOR", "divisors pair up", "each bit is independent", "only perfect squares have an odd number of divisors".
  4. Replace the loop with the invariant: a formula, a loop over 32 bits, or a loop over log n squarings.
  5. Mind the edges: negative numbers, 32-bit overflow, modulo 10⁹ + 7, and 0 / 1.

3. Seeing a problem: how to spot Math / Bit Manipulation

Trigger words

  • "without using * / %", "without + −", "in O(1) extra space" with numbers that appear twice / three times
  • huge exponents or counts: n up to 10⁹ or 10¹⁵, "return modulo 10⁹ + 7"
  • "bitwise AND / OR / XOR", "number of 1 bits", "power of two"
  • "count primes", "divisors", "gcd of all pairs", "factorial"
  • a simulation over a huge range (bulbs, steps on a number line)

Shape of the input

  • One or two integers, often enormous.
  • An array where every value appears k times except a few.
  • Brute-force smell: a loop up to n with n = 10⁹, or all pairs of an array of 10⁵.
The one question to ask"Is there a property of the numbers themselves (bits, factors, parity) that makes most of this work unnecessary?"

4. When to use it, and when not to

Reach for math / bits when…Prefer something else when…
An exponent or count is huge (10⁹+) and the step is a multiplicationThe step isn't a product or linear map: look for DP or a closed form
Values appear in pairs/triples and you need O(1) spaceYou may use O(n) space and clarity matters: a hash map is fine
Operations are bitwise and bits don't interactCarries connect the bits (addition): handle them explicitly
You need primes or divisors of many numbersYou need them for one number: trial division up to √n is enough

Cost: fast power is O(log n), per-bit loops are O(32 · n), the sieve is O(n log log n), and gcd counting over multiples is O(M log M) by the harmonic series.

5. The Python template (memorize this)

# A) binary exponentiation: x**n mod m in O(log n)
def fast_pow(x, n, m):
    result = 1
    x %= m
    while n:
        if n & 1:                 # this bit of n is set
            result = result * x % m
        x = x * x % m             # x, x^2, x^4, x^8, ...
        n >>= 1
    return result


# B) XOR cancelling: the value that appears an odd number of times
def odd_one_out(nums):
    acc = 0
    for v in nums:
        acc ^= v                  # a ^ a = 0, so pairs vanish
    return acc


# C) sieve of Eratosthenes: is_prime for every number below n
def sieve(n):
    is_prime = [True] * n
    is_prime[0:2] = [False, False]
    p = 2
    while p * p < n:
        if is_prime[p]:
            for multiple in range(p * p, n, p):
                is_prime[multiple] = False
        p += 1
    return is_prime

What the code is doing, line by line:

  1. n & 1 reads the lowest bit of the exponent; n >>= 1 moves to the next bit. Each set bit multiplies in the matching power x^(2^k).
  2. Reducing modulo m after every multiplication keeps the numbers small (in Python it's about speed; in other languages it prevents overflow).
  3. XOR is commutative and associative, so the order doesn't matter: every value that occurs an even number of times cancels to 0.
  4. The sieve starts crossing out at p * p: smaller multiples of p have a smaller prime factor and were crossed out already.

Dry run of template A for 3¹³ mod 1000 (13 = 1101 in binary):

bit of nx (before squaring)result
133
093
181243
1561 (= 6561 mod 1000)323 (= 243 · 561 mod 1000)

Four squarings instead of twelve multiplications; 3¹³ = 1,594,323, so the last three digits 323 check out.

6. How to remember it forever

Memory hook: "Square and skip"Exponents: square the base, multiply only on set bits. XOR: pairs vanish. Bits: one column at a time.
How this hook works: what “Square and skip” means

What the slogan means, phrase by phrase

“Square”
In fast exponentiation, square the base every round: x, x², x⁴, x⁸ …
“and skip”
Multiply that power into the result only when the matching bit of the exponent is 1. Skip it otherwise.
“XOR: pairs vanish”
a ^ a = 0 and a ^ 0 = a, so XOR-ing everything cancels every pair and leaves the odd one out.
“Bits: one column at a time”
Each bit position is independent, so you can count or decide per column.

Why this picture fits the pattern: Math and bit problems each hide one structural fact (binary digits, pairs cancelling, divisors coming in pairs) that turns a slow loop into O(log n) or O(1). The slogan bundles the three you'll use most.

The story → the code

In the storyIn the code
Square the basex = x * x % m
This bit is set: multiplyif n & 1: result = result * x % m
Next bitn >>= 1
Pairs vanishacc ^= v

Watch it on numbers

Compute 3¹³. 13 in binary is 1101 = 8 + 4 + 1.

  1. Bit 1 is set: result = 3. Square: x = 9.
  2. Bit 0: skip. Square: x = 81.
  3. Bit 1: result = 3 × 81 = 243. Square: x = 6561.
  4. Bit 1: result = 243 × 6561 = 1,594,323. That's 4 rounds instead of 12 multiplications.
  5. XOR on [4, 1, 2, 1, 2]: the 1s cancel, the 2s cancel, 4 is left.

The trap it saves you from

Forgetting % m after every multiply (the numbers grow huge and slow), and Python's negative integers behaving as if they had infinite bits. Mask with & 0xFFFFFFFF for 32-bit answers.

It still works when…

Single Number is pairs vanishing. Counting Bits uses bits[i] = bits[i >> 1] + (i & 1). Bulb Switcher: a bulb is toggled once per divisor, divisors come in pairs, so only perfect squares stay on.

Picture

A light switch flipped twice is back where it started: that's XOR, and it's also why only perfect-square bulbs stay on.

Chant

"Bits are independent, divisors come in pairs, squares grow fast."

Safety rule

"Mask, mod, and mind the sign." 32-bit masks in Python, mod after every multiply, and negative numbers.

7. LeetCode problems, solved step by step

New to this pattern? Start with theseSolve 1492. The kth Factor of n, then 7. Reverse Integer, then 50. Pow(x, n). They are marked Start here below. Read the explanation, press Play on the step-through, then close the page and solve it yourself on LeetCode.
Medium 50. Pow(x, n) Start here Google Meta Amazon Cisco Microsoft Math

Problem: Compute xⁿ for a float x and an integer n (possibly negative).

Example 1
Input: x = 2.00000, n = 10
Output: 1024.00000
Example 2
Input: x = 2.10000, n = 3
Output: 9.26100

Constraints: -100.0 < x < 100.0 · -2³¹ ≤ n ≤ 2³¹-1 · n is an integer. · Either x is not zero or n > 0. · -10⁴ ≤ xn ≤ 10⁴

Hint 1

How can you get x⁸ with only 3 multiplications?

Hint 2

Use the binary representation of n.

From brute force to the pattern: n multiplications vs log n squarings.

Spot it: Binary exponentiation: xⁿ is the product of x^(2^k) over the set bits of n. Square the base each step.

Why not another pattern? Multiplying n times is O(n) with |n| up to 2³¹.

Approach:

  1. If n < 0: x = 1/x, n = −n.
  2. While n: if n & 1, result *= x; x *= x; n >>= 1.
class Solution:
    def myPow(self, x: float, n: int) -> float:
        if n < 0:
            x, n = 1 / x, -n  # x^-n = (1/x)^n
        result = 1.0
        while n:
            if n & 1:
                result *= x  # this power of two is part of n
            x *= x  # x, x^2, x^4, x^8, ...
            n >>= 1
        return result

What the code is doing, line by line:

  1. After k squarings, x holds x^(2^k).
  2. Each set bit of n multiplies in the matching power.
  3. Negative exponents invert the base first.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • n = 0 → 1.
  • Negative n.
  • n = −2³¹.

Complexity: O(log n) time, O(1) space.

Medium 260. Single Number III Google Amazon Array

Problem: Exactly two elements appear once; all others twice. Return the two (any order) in O(n) time, O(1) space.

Example 1
Input: nums = [1,2,1,3,2,5]
Output: [3,5]
Explanation: [5, 3] is also a valid answer.
Example 2
Input: nums = [-1,0]
Output: [-1,0]

Constraints: 2 ≤ nums.length ≤ 3 * 10⁴ · -2³¹ ≤ nums[i] ≤ 2³¹ - 1 · Each integer in nums will appear twice, only two integers will appear once.

Hint 1

XOR of everything gives a ^ b. How can you separate a from b?

Hint 2

Pick a bit where a and b differ and split the array by it.

From brute force to the pattern: A set or counter is O(n) space; the XOR split is O(1).

Spot it: XOR cancels pairs, leaving a ^ b. Any set bit of it is a bit where a and b differ; split all numbers by that bit and XOR each group separately.

Why not another pattern? A hash set uses O(n) space.

Approach:

  1. both = XOR of all.
  2. bit = both & −both (lowest set bit).
  3. XOR the numbers with that bit set → a; b = both ^ a.
class Solution:
    def singleNumber(self, nums: List[int]) -> List[int]:
        both = 0
        for x in nums:
            both ^= x  # pairs cancel: a ^ b remains
        bit = both & -both  # lowest bit where a and b differ
        a = 0
        for x in nums:
            if x & bit:
                a ^= x  # only one of the two singles has this bit
        return [a, both ^ a]

What the code is doing, line by line:

  1. x & −x isolates the lowest set bit (two's complement).
  2. Each pair lands in the same group and cancels; the singles land in different groups.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Negative numbers.
  • Zero as one of the answers.
  • Two elements only.

Complexity: O(n) time, O(1) space.

Medium 204. Count Primes Google Amazon Microsoft ArrayMath

Problem: Count primes strictly less than n.

Example 1
Input: n = 10
Output: 4
Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7.
Example 2
Input: n = 0
Output: 0

Constraints: 0 ≤ n ≤ 5 * 10⁶

Hint 1

Instead of testing each number, eliminate composites.

Hint 2

Each prime crosses out its multiples.

From brute force to the pattern: Trial division: O(n√n). Sieve: O(n log log n).

Spot it: Primality for every number below n → the Sieve of Eratosthenes: each prime crosses out its multiples starting at p².

Why not another pattern? Trial division for each number is O(n√n).

Approach:

  1. is_prime = [True] * n; 0 and 1 are not prime.
  2. For p up to √n: if prime, mark p², p² + p, … as not prime.
  3. Count the remaining Trues.
class Solution:
    def countPrimes(self, n: int) -> int:
        if n < 3:
            return 0
        is_prime = [True] * n
        is_prime[0] = is_prime[1] = False
        p = 2
        while p * p < n:
            if is_prime[p]:
                is_prime[p * p::p] = [False] * len(range(p * p, n, p))  # cross out multiples
            p += 1
        return sum(is_prime)

What the code is doing, line by line:

  1. Multiples below p² were already crossed out by smaller primes.
  2. Slice assignment does the crossing out at C speed.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • n ≤ 2 → 0.
  • n = 3 → 1.
  • Large n.

Complexity: O(n log log n) time, O(n) space.

8. Common mistakes

Python's unbounded integersBit tricks that rely on 32-bit overflow (Sum of Two Integers, negative numbers in Single Number II) need an explicit & 0xFFFFFFFF mask and a conversion back to signed.
Forgetting the modulo inside the loopTaking % MOD only at the end lets numbers grow to millions of digits and makes the code slow.
// with negativesPython floors toward −∞ (-7 // 2 == -4). Problems that want truncation toward zero need int(a / b) or working with absolute values.
Floating point for exact answersint(n ** 0.5) can be off by one for large n; use math.isqrt.
Off-by-one in sieves"Primes less than n" vs "≤ n" changes the array size; 0 and 1 are not prime.

9. Self-check quiz

How many squarings does binary exponentiation need for n = 2,000,000,000?

One squaring per bit of n, and 2·10⁹ has 31 bits.

Every number appears twice except one. Fastest O(1)-space way to find it?

Pairs cancel under XOR; the leftover is the single number.

Every number appears three times except one. What still works in O(1) space?

Tripled numbers add a multiple of 3 to each bit count; the remainder is the single number's bit.

Which numbers have an odd number of divisors?

Divisors pair up as (d, n/d); only √n of a perfect square pairs with itself.

10. Practice list (in order)

#ProblemLevelData structureTwist
202Happy NumberEasyMathHash SetSolved in 04 · Fast & Slow Pointers: Implicit "next" = sum of digit squares
367Valid Perfect SquareEasyMathSolved in 09 · Modified Binary Search: Binary search over candidate roots 1..num
50Pow(x, n)MediumMathFast exponentiation: square the base, multiply it in when the current bit of n is 1
260Single Number IIIMediumArrayXOR all → a ^ b; its lowest set bit splits the numbers into two groups, one per answer
204Count PrimesMediumArrayMathSieve of Eratosthenes: cross out multiples of each prime from p²
7Reverse IntegerMediumMathPop digits with % 10 and push with × 10; return 0 outside the 32-bit range
29Divide Two IntegersMediumMathSubtract the largest shifted divisor (divisor << k) that fits, adding 1 << k to the quotient
137Single Number IIMediumArrayCount each bit position mod 3: the leftover bits form the single number
172Factorial Trailing ZeroesMediumMathCount factors of 5: n//5 + n//25 + n//125 + …
223Rectangle AreaMediumMathArea A + area B − overlap; the overlap's width is max(0, min right − max left)
319Bulb SwitcherMediumMathBulb i is toggled once per divisor; only perfect squares have an odd count: answer ⌊√n⌋
371Sum of Two IntegersMediumMathXOR adds without carry, AND << 1 is the carry; repeat in 32-bit with a mask
372Super PowMediumArrayMatha^(10·x + d) = (a^x)^10 · a^d: process the exponent's digits left to right, mod 1337
754Reach a NumberMediumMathWalk right until the sum S ≥ |target| and S − target is even; flipping a step k changes S by 2k
866Prime PalindromeMediumMathGenerate odd-length palindromes from their left halves in increasing order; test primality (even-length ones are divisible by 11)
1318Minimum Flips to Make a OR b Equal to cMediumMathPer bit: if c's bit is 1, need one of a/b set; if 0, flip every set bit of a and b
1344Angle Between Hands of a ClockMediumMathMinute hand 6° per minute; hour hand 30° per hour + 0.5° per minute; take the smaller angle
1492The kth Factor of nMediumMathDivisors come in pairs (d, n/d): list the small ones up to √n, then mirror
1680Concatenation of Consecutive Binary NumbersMediumMathShift left by the bit length of i, OR in i, reduce mod 10⁹ + 7
1922Count Good NumbersMediumMath5 choices at even indices, 4 (primes) at odd indices: 5^⌈n/2⌉ · 4^⌊n/2⌋ with fast power
2396Strictly Palindromic NumberMediumMathIn base n − 2, every n ≥ 5 is written "12" (and 4 is "100" in base 2): never palindromic
3513Number of Unique XOR Triplets IMediumArrayMathWith a permutation of 1..n (n ≥ 3), every value below the next power of two is reachable
3702Longest Subsequence With Non-Zero Bitwise XORMediumArrayTotal XOR ≠ 0 → n; all zeros → 0; otherwise drop one non-zero element → n − 1
3896Minimum Operations to Transform Array into Alternating PrimeMediumArrayMathSieve once; even index → distance to the next prime; odd index → 0, or 1 (2 for the value 2) if it's prime
1823Find the Winner of the Circular GameMediumMathJosephus recurrence: winner(i) = (winner(i − 1) + k) mod i, starting from winner(1) = 0
318Maximum Product of Word LengthsMediumStringArray26-bit mask per word; two words share no letters iff their masks AND to 0
3514Number of Unique XOR Triplets IIMediumArrayHash SetValues ≤ 1500 means XORs fit in 11 bits: set of pair XORs, then XOR each with every value
3644Maximum K to Sort a PermutationMediumArrayk = AND of all misplaced values (0 if already sorted)
3047Find the Largest Area of Square Inside Two RectanglesMediumArrayMathFor every pair, the intersection is a rectangle; the largest square side is min(width, height)
3648Minimum Sensors to Cover GridMediumMathEach sensor covers a (2k+1)×(2k+1) square: ceil(n/(2k+1)) · ceil(m/(2k+1))
779K-th Symbol in GrammarMediumMathEach step copies (0→01, 1→10): symbol k flips once per 1-bit of k−1, so the answer is popcount(k−1) mod 2
2571Minimum Operations to Reduce an Integer to 0MediumMathWalk the bits: a lone 1 is subtracted; a run of 1s is turned into one carry (add 1)
477Total Hamming DistanceMediumArrayPer bit: (count of 1s) × (count of 0s) pairs differ there
843Guess the WordHardStringArrayGuess the word that minimises the largest group of candidates sharing a match count; keep only consistent words
3312Sorted GCD Pair QueriesHardArrayMathPairs with gcd exactly g = C(multiples of g, 2) − pairs with gcd 2g, 3g, …; prefix sums + binary search
233Number of Digit OneHardMathSolved in 15 · Dynamic Programming Patterns: Count 1s per digit position from the high part, the current digit and the low part
2081Sum of k-Mirror NumbersHardMathGenerate base-10 palindromes in increasing order (from their halves) and keep those that are also base-k palindromes
829Consecutive Numbers SumHardMathk consecutive numbers starting at x sum to kx + k(k−1)/2: count k where (n − k(k−1)/2) is a positive multiple of k

Worked solutions for the practice list

Problems already solved in section 7 link back up there, and rows marked "Solved in …" link to the page where that problem is worked through. Every other problem from the table is solved here.

Medium 2396. Strictly Palindromic Number Google Math

Problem: Is n palindromic in every base from 2 to n − 2?

Example 1
Input: n = 9
Output: false
Explanation: In base 2: 9 = 1001 (base 2), which is palindromic. In base 3: 9 = 100 (base 3), which is not palindromic. Therefore, 9 is not strictly palindromic so we return false. Note that in bases 4, 5, 6, and 7, n = 9 is also not palindromic.
Example 2
Input: n = 4
Output: false
Explanation: We only consider base 2: 4 = 100 (base 2), which is not palindromic. Therefore, we return false.

Constraints: 4 ≤ n ≤ 10⁵

Hint 1

Write n in base n − 2.

Hint 2

Is there any n that passes?

From brute force to the pattern: Checking every base is O(n log n); the observation is constant time.

Spot it: A math observation: n = 1 · (n − 2) + 2, so in base n − 2 it's "12" for n ≥ 5, not a palindrome. n = 4 is "100" in base 2.

Why not another pattern? Converting to every base works but proves nothing; the answer is always false.

Approach:

  1. Return False.
class Solution:
    def isStrictlyPalindromic(self, n: int) -> bool:
        return False  # base n - 2 always gives "12" (for n >= 5); n = 4 is "100" in base 2

What the code is doing, line by line:

  1. For n ≥ 5, n − 2 ≥ 3 > 2, so the digits are 1 and 2.
  2. The only remaining case, n = 4, fails in base 2.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • n = 4.
  • n = 5.
  • Large n.

Complexity: O(1).

Medium 3896. Minimum Operations to Transform Array into Alternating Prime Google ArrayMath

Problem: Increment elements so that even indices hold primes and odd indices hold non-primes. Return the minimum number of increments.

Example 1
Input: nums = [1,2,3,4]
Output: 3
Explanation: The element at index 0 must be prime. Increment nums[0] = 1 to 2, using 1 operation. The element at index 1 must be non-prime. Increment nums[1] = 2 to 4, using 2 operations. The element at index 2 is already prime. The element at index 3 is already non-prime. Total operations = 1 + 2 = 3.
Example 2
Input: nums = [5,6,7,8]
Output: 0
Explanation: The elements at indices 0 and 2 are already prime. The elements at indices 1 and 3 are already non-prime. No operations are needed.

Constraints: 1 ≤ nums.length ≤ 10⁵ · 1 ≤ nums[i] ≤ 10⁵

Hint 1

Each index can be handled on its own.

Hint 2

Precompute primes with a sieve and the next prime above each value.

Hint 3

What's the cheapest way to make a prime non-prime by incrementing?

From brute force to the pattern: Trial division while incrementing is O(n · gap · √M); the sieve makes each index O(1).

Spot it: Each element is independent. A sieve (plus a "next prime at or above x" table) answers even indices; an odd index only needs work if it's prime: x + 1 is non-prime unless x = 2 (3 is prime, so it takes 2 steps to 4).

Why not another pattern? Testing primality by trial division while incrementing is much slower than one sieve.

Approach:

  1. Sieve up to a bit above 10⁵ (the next prime after 10⁵ is 100003).
  2. next_prime[v] from the top down.
  3. Sum per index: even → next_prime[x] − x; odd → 0 if not prime, else 2 if x == 2, else 1.
class Solution:
    def minOperations(self, nums: List[int]) -> int:
        LIMIT = max(nums) + 100  # a prime always appears within 100 above any value <= 10^5
        is_prime = [True] * (LIMIT + 1)
        is_prime[0] = is_prime[1] = False
        p = 2
        while p * p <= LIMIT:
            if is_prime[p]:
                is_prime[p * p::p] = [False] * len(range(p * p, LIMIT + 1, p))
            p += 1
        next_prime = [0] * (LIMIT + 2)
        nxt = LIMIT + 1
        for v in range(LIMIT, -1, -1):
            if is_prime[v]:
                nxt = v
            next_prime[v] = nxt  # smallest prime >= v
        ops = 0
        for i, x in enumerate(nums):
            if i % 2 == 0:
                ops += next_prime[x] - x  # climb to a prime
            elif is_prime[x]:
                ops += 2 if x == 2 else 1  # x + 1 is even and > 2, except 2 + 1 = 3
        return ops

What the code is doing, line by line:

  1. Increments only go up, so an even index needs the nearest prime at or above it.
  2. For an odd prime x > 2, x + 1 is even and greater than 2, hence composite.
  3. Prime gaps below 10⁵ are under 100, so the sieve limit is safe.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Value 1 at an even index (next prime 2).
  • Value 2 at an odd index (needs 2 steps).
  • Already alternating → 0.

Complexity: O(M log log M + n) time, O(M) space.

Medium 7. Reverse Integer Start here Google Meta Amazon Microsoft Apple Math

Problem: Reverse the digits of a 32-bit signed integer; return 0 if the result overflows.

Example 1
Input: x = 123
Output: 321
Example 2
Input: x = -123
Output: -321

Constraints: -2³¹ ≤ x ≤ 2³¹ - 1

Hint 1

Take digits from the end with % and //.

Hint 2

Watch for the 32-bit overflow.

From brute force to the pattern: String reversal is fine in Python; the digit loop is what C++/Java need.

Spot it: Digit arithmetic: x % 10 takes the last digit, x // 10 drops it, rev · 10 + d appends it. Work with |x| and restore the sign.

Why not another pattern? String reversal works in Python but hides the overflow reasoning interviewers ask about.

Approach:

  1. sign, x = |x|.
  2. While x: rev = rev · 10 + x % 10, x //= 10.
  3. Apply the sign; return 0 outside [−2³¹, 2³¹ − 1].
class Solution:
    def reverse(self, x: int) -> int:
        sign = -1 if x < 0 else 1
        x = abs(x)
        rev = 0
        while x:
            rev = rev * 10 + x % 10  # move the last digit of x to the end of rev
            x //= 10
        rev *= sign
        return rev if -2**31 <= rev <= 2**31 - 1 else 0

What the code is doing, line by line:

  1. Working with abs(x) avoids Python's floor-division surprises with negatives.
  2. In a 32-bit language, check rev > (2³¹ − 1) // 10 before multiplying.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Negative numbers.
  • Trailing zeros (120 → 21).
  • Overflow (1534236469 → 0).

Complexity: O(log x) time, O(1) space.

Medium 29. Divide Two Integers Google Meta Amazon Math

Problem: Divide without *, / or %, truncating toward zero; clamp to the 32-bit range.

Example 1
Input: dividend = 10, divisor = 3
Output: 3
Explanation: 10/3 = 3.33333.. which is truncated to 3.
Example 2
Input: dividend = 7, divisor = -3
Output: -2
Explanation: 7/-3 = -2.33333.. which is truncated to -2.

Constraints: -2³¹ ≤ dividend, divisor ≤ 2³¹ - 1 · divisor != 0

Hint 1

Repeated subtraction is too slow. How can you subtract big multiples of the divisor quickly?

Hint 2

Use left shifts to double the divisor.

From brute force to the pattern: Subtracting one divisor at a time is O(quotient); shifting is O(32).

Spot it: Long division in binary: bit shifts double the divisor. From the largest divisor << k that fits, subtract and add 1 << k — each bit of the quotient decided once.

Why not another pattern? Repeated subtraction is O(quotient), up to 2³¹ steps.

Approach:

  1. Handle the sign; work with absolute values.
  2. For k from 31 down to 0: if (b << k) ≤ a: a −= b << k, q += 1 << k.
  3. Apply the sign and clamp.
class Solution:
    def divide(self, dividend: int, divisor: int) -> int:
        negative = (dividend < 0) != (divisor < 0)
        a, b = abs(dividend), abs(divisor)
        q = 0
        for k in range(31, -1, -1):
            if (b << k) <= a:  # divisor * 2^k still fits
                a -= b << k
                q += 1 << k  # this bit of the quotient is 1
        q = -q if negative else q
        return max(-2**31, min(2**31 - 1, q))  # only -2^31 / -1 overflows

What the code is doing, line by line:

  1. Trying shifts from large to small decides the quotient's bits from the top, like long division.
  2. Truncation toward zero comes from working with absolute values.
  3. The only overflow case is −2³¹ / −1.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • −2³¹ / −1 → clamp.
  • Negative operands.
  • Divisor larger than the dividend → 0.

Complexity: O(32) time, O(1) space.

Medium 137. Single Number II Google Amazon Microsoft Array

Problem: Every element appears three times except one, which appears once. Find it in O(n) time and O(1) space.

Example 1
Input: nums = [2,2,3,2]
Output: 3
Example 2
Input: nums = [0,1,0,1,0,1,99]
Output: 99

Constraints: 1 ≤ nums.length ≤ 3 * 10⁴ · -2³¹ ≤ nums[i] ≤ 2³¹ - 1 · Each element in nums appears exactly three times except for one element which appears once.

Hint 1

Look at one bit position at a time.

Hint 2

How many times does each bit appear among the tripled numbers?

From brute force to the pattern: A counter uses O(n) space; per-bit counting uses O(1).

Spot it: For each bit position, the triple elements contribute a multiple of 3 ones. So (count of ones) % 3 is exactly the single number's bit there.

Why not another pattern? A hash map works but uses O(n) space; XOR only cancels pairs, not triples.

Approach:

  1. For each of the 32 bits: count numbers with that bit set; if count % 3, set the bit in the answer.
  2. Fix the sign for negative numbers (bit 31).
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        result = 0
        for b in range(32):
            ones = sum((x >> b) & 1 for x in nums)  # how many numbers have bit b set
            if ones % 3:
                result |= 1 << b  # tripled numbers contribute multiples of 3
        if result >= 2**31:
            result -= 2**32  # bit 31 set: it's a negative number in 32-bit
        return result

What the code is doing, line by line:

  1. Python's >> on negatives sign-extends, and & 1 reads the two's-complement bit correctly.
  2. The final adjustment converts the 32-bit pattern back to a signed integer.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Negative single number.
  • Zero as the single number.
  • One element.

Complexity: O(32 · n) time, O(1) space.

Medium 172. Factorial Trailing Zeroes Google Math

Problem: Return the number of trailing zeros in n!.

Example 1
Input: n = 3
Output: 0
Explanation: 3! = 6, no trailing zero.
Example 2
Input: n = 5
Output: 1
Explanation: 5! = 120, one trailing zero.

Constraints: 0 ≤ n ≤ 10⁴

Hint 1

Where do trailing zeros come from?

Hint 2

Count how many factors of 5 appear in 1..n.

From brute force to the pattern: Computing n! is O(n) big multiplications; counting 5s is O(log n).

Spot it: Each trailing zero needs a factor 10 = 2 · 5, and 2s are plentiful, so count the 5s in 1..n (multiples of 25 give two, …).

Why not another pattern? Computing n! is huge; counting zeros of the number is wasteful.

Approach:

  1. zeros = 0; while n: n //= 5; zeros += n.
class Solution:
    def trailingZeroes(self, n: int) -> int:
        zeros = 0
        while n:
            n //= 5
            zeros += n  # multiples of 5, then of 25, 125, ...
        return zeros

What the code is doing, line by line:

  1. n // 5 counts multiples of 5; dividing again counts multiples of 25 (an extra 5 each), and so on.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • n < 5 → 0.
  • n = 25 → 6.
  • Large n.

Complexity: O(log₅ n) time, O(1) space.

Medium 223. Rectangle Area Google Microsoft Math

Problem: Return the total area covered by two axis-aligned rectangles.

Example 1
Input: ax1 = -3, ay1 = 0, ax2 = 3, ay2 = 4, bx1 = 0, by1 = -1, bx2 = 9, by2 = 2
Output: 45
Example 2
Input: ax1 = -2, ay1 = -2, ax2 = 2, ay2 = 2, bx1 = -2, by1 = -2, bx2 = 2, by2 = 2
Output: 16

Constraints: -10⁴ ≤ ax1 ≤ ax2 ≤ 10⁴ · -10⁴ ≤ ay1 ≤ ay2 ≤ 10⁴ · -10⁴ ≤ bx1 ≤ bx2 ≤ 10⁴ · -10⁴ ≤ by1 ≤ by2 ≤ 10⁴

Hint 1

Add the two areas. What did you count twice?

Hint 2

How do you compute the overlapping rectangle?

From brute force to the pattern: Grid counting is infeasible; inclusion–exclusion is constant time.

Spot it: Inclusion–exclusion: add both areas, subtract the intersection. The intersection's sides come from min of right edges and max of left edges.

Why not another pattern? Counting unit squares is impossible for coordinates up to 10⁴.

Approach:

  1. w = max(0, min(ax2, bx2) − max(ax1, bx1)), same for height.
  2. Return areaA + areaB − w · h.
class Solution:
    def computeArea(self, ax1: int, ay1: int, ax2: int, ay2: int, bx1: int, by1: int, bx2: int, by2: int) -> int:
        overlap_w = max(0, min(ax2, bx2) - max(ax1, bx1))  # 0 if they don't overlap horizontally
        overlap_h = max(0, min(ay2, by2) - max(ay1, by1))
        area_a = (ax2 - ax1) * (ay2 - ay1)
        area_b = (bx2 - bx1) * (by2 - by1)
        return area_a + area_b - overlap_w * overlap_h  # don't count the shared part twice

What the code is doing, line by line:

  1. The overlap is itself a rectangle, bounded by the inner edges.
  2. A negative width means no overlap; max(0, …) handles it.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • No overlap.
  • One inside the other.
  • Touching edges (overlap 0).

Complexity: O(1).

Medium 319. Bulb Switcher Google Amazon Math

Problem: n bulbs start off; on round i every i-th bulb toggles. How many are on after n rounds?

Example 1
Input: n = 3
Output: 1
Explanation: At first, the three bulbs are [off, off, off]. After the first round, the three bulbs are [on, on, on]. After the second round, the three bulbs are [on, off, on]. After the third round, the three bulbs are [on, off, off]. So you should return 1 because there is only one bulb is on.
Example 2
Input: n = 0
Output: 0

Constraints: 0 ≤ n ≤ 10⁹

Hint 1

How many times is bulb k toggled?

Hint 2

Which numbers have an odd number of divisors?

From brute force to the pattern: Simulation is far too slow; the divisor-parity argument gives a formula.

Spot it: Bulb k is toggled once for each divisor of k. Divisors pair up (d, k/d) except for perfect squares → only perfect squares end up on.

Why not another pattern? Simulating is O(n log n) with n up to 10⁹.

Approach:

  1. Return isqrt(n).
from math import isqrt

class Solution:
    def bulbSwitch(self, n: int) -> int:
        return isqrt(n)  # 1, 4, 9, ... have an odd number of divisors

What the code is doing, line by line:

  1. An odd number of toggles leaves a bulb on.
  2. isqrt counts the perfect squares ≤ n exactly (no float rounding).

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • n = 0 → 0.
  • Perfect square n.
  • Large n.

Complexity: O(log n) time, O(1) space.

Medium 371. Sum of Two Integers Google Meta Amazon Microsoft Math

Problem: Add two integers without using + or −.

Example 1
Input: a = 1, b = 2
Output: 3
Example 2
Input: a = 2, b = 3
Output: 5

Constraints: -1000 ≤ a, b ≤ 1000

Hint 1

What does XOR compute? What does AND compute?

Hint 2

In Python, integers are unbounded: mask to 32 bits.

From brute force to the pattern: Bit-by-bit addition with an explicit carry loop is the same idea, one bit at a time.

Spot it: Bitwise addition: a ^ b is the sum ignoring carries, (a & b) << 1 is the carries. Repeat until no carry. In Python, mask to 32 bits to emulate fixed-width integers.

Why not another pattern? sum([a, b]) sidesteps the point; the question is about the binary adder.

Approach:

  1. mask = 0xFFFFFFFF.
  2. While b: a, b = (a ^ b) & mask, ((a & b) << 1) & mask.
  3. Convert back: if a > 0x7FFFFFFF, it's negative: ~(a ^ mask).
class Solution:
    def getSum(self, a: int, b: int) -> int:
        mask = 0xFFFFFFFF  # emulate 32-bit integers
        a &= mask
        b &= mask
        while b:
            a, b = (a ^ b) & mask, ((a & b) << 1) & mask  # sum without carry, then the carry
        return a if a <= 0x7FFFFFFF else ~(a ^ mask)  # back to a signed value

What the code is doing, line by line:

  1. Each round moves the carries one position left; they disappear after at most 32 rounds.
  2. ~(a ^ mask) turns a 32-bit two's-complement pattern into Python's negative integer.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Negative numbers.
  • a = −b (result 0).
  • Zero.

Complexity: O(32) time, O(1) space.

Medium 372. Super Pow Google ArrayMath

Problem: Compute a^b mod 1337 where b is a huge number given as a digit array.

Example 1
Input: a = 2, b = [3]
Output: 8
Explanation: The array b = [3] represents the exponent 3. Therefore, a³ = 2³ = 8, so the result is 8.
Example 2
Input: a = 2, b = [1,0]
Output: 1024
Explanation: The array b = [1, 0] represents the exponent 10. Therefore, a¹⁰ = 2¹⁰ = 1024, so the result is 1024.

Constraints: 1 ≤ a ≤ 2³¹ - 1 · 1 ≤ b.length ≤ 2000 · 0 ≤ b[i] ≤ 9 · b does not contain leading zeros.

Hint 1

How does a^(10x + d) relate to a^x?

Hint 2

Process the digits of b from left to right.

From brute force to the pattern: Converting b to an integer creates a 2000-digit number; the digit recurrence never does.

Spot it: Modular exponentiation digit by digit: appending digit d to the exponent turns r = a^x into r^10 · a^d (mod 1337).

Why not another pattern? Building b as an integer and calling pow works in Python, but the digit recurrence is the intended idea.

Approach:

  1. result = 1.
  2. For each digit d: result = pow(result, 10, 1337) · pow(a, d, 1337) % 1337.
class Solution:
    def superPow(self, a: int, b: List[int]) -> int:
        MOD = 1337
        result = 1
        for d in b:
            result = pow(result, 10, MOD) * pow(a, d, MOD) % MOD  # exponent x -> 10x + d
        return result

What the code is doing, line by line:

  1. If the exponent so far is x, appending d makes it 10x + d.
  2. a^(10x + d) = (a^x)^10 · a^d, all reducible mod 1337.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • a multiple of 1337 → 0.
  • b = [0] style exponents.
  • Large a.

Complexity: O(len(b) · log 10) time, O(1) space.

Medium 754. Reach a Number Google Math

Problem: Step i moves i units left or right. Return the fewest steps to land exactly on target.

Example 1
Input: target = 2
Output: 3
Explanation: On the 1st move, we step from 0 to 1 (1 step). On the 2nd move, we step from 1 to -1 (2 steps). On the 3rd move, we step from -1 to 2 (3 steps).
Example 2
Input: target = 3
Output: 2
Explanation: On the 1st move, we step from 0 to 1 (1 step). On the 2nd move, we step from 1 to 3 (2 steps).

Constraints: -10⁹ ≤ target ≤ 10⁹ · target != 0

Hint 1

Go right every step until you reach or pass the target.

Hint 2

What happens to the total if you flip one step from right to left?

From brute force to the pattern: BFS on positions grows exponentially; the parity argument is O(√t).

Spot it: By symmetry use |target|. Take steps 1, 2, …, k all to the right until the sum reaches the target. Flipping step j subtracts 2j, so we need sum − target to be even — a parity argument.

Why not another pattern? BFS over positions explodes.

Approach:

  1. t = |target|, k = 0, s = 0.
  2. While s < t or (s − t) is odd: k += 1, s += k.
  3. Return k.
class Solution:
    def reachNumber(self, target: int) -> int:
        t = abs(target)  # left and right are symmetric
        k = 0
        s = 0
        while s < t or (s - t) % 2:
            k += 1
            s += k  # take one more step to the right
        return k  # flip steps worth (s - t) / 2 to land exactly

What the code is doing, line by line:

  1. Flipping a set of steps that sums to (s − t)/2 reduces the total by exactly s − t; any even surplus can be fixed.
  2. An odd surplus can't be fixed by flips, so another step is needed.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Negative target.
  • Target reached exactly by 1 + 2 + … + k.
  • Target needing two extra steps.

Complexity: O(√|target|) time, O(1) space.

Hard 843. Guess the Word Google StringArray

Problem: Find the secret 6-letter word with Master.guess(word) (returns exact-position matches) within the allowed guesses.

Example 1
Input: secret = "acckzz", words = ["acckzz","ccbazz","eiowzz","abcczz"], allowedGuesses = 10
Output: You guessed the secret word correctly.
Explanation: master.guess("aaaaaa") returns -1, because "aaaaaa" is not in words. master.guess("acckzz") returns 6, because "acckzz" is secret and has all 6 matches. master.guess("ccbazz") returns 3, because "ccbazz" has 3 matches. master.guess("eiowzz") returns 2, because "eiowzz" has 2 matches. master.guess("abcczz") returns 4, because "abcczz" has 4 matches. We made 5 calls to master.guess, and one of them was the secret, so we pass the test case.
Example 2
Input: secret = "hamada", words = ["hamada","khaled"], allowedGuesses = 10
Output: You guessed the secret word correctly.
Explanation: Since there are two words, you can guess both.

Constraints: 1 ≤ words.length ≤ 100 · words[i].length == 6 · words[i] consist of lowercase English letters. · All the strings of words are unique. · secret exists in words. · 10 ≤ allowedGuesses ≤ 30

Hint 1

After a guess returns k matches, which words can still be the secret?

Hint 2

Choose guesses that split the candidates as evenly as possible.

From brute force to the pattern: Guessing words one by one can take 100 guesses; the minimax filter needs about 10.

Spot it: Each guess partitions the candidates by match count; only the group matching the reply survives. Choosing the guess whose largest group is smallest (minimax) shrinks the candidates fastest. It's a counting/combinatorics game rather than a data-structure problem.

Why not another pattern? Random guesses usually work but can fail the strict tests; guessing in order fails easily.

Approach:

  1. matches(a, b) = positions where letters agree.
  2. Pick the candidate whose worst-case group (over match counts with all other candidates) is smallest.
  3. Guess it; if 6, done. Otherwise keep candidates with exactly the same match count to the guess.
from collections import Counter

class Solution:
    def findSecretWord(self, words: List[str], master: "Master") -> None:
        def matches(a, b):
            return sum(x == y for x, y in zip(a, b))

        candidates = words[:]
        while candidates:
            guess = min(candidates, key=lambda w: max(Counter(matches(w, o) for o in candidates).values()))  # minimax
            hit = master.guess(guess)
            if hit == 6:
                return
            candidates = [w for w in candidates if matches(w, guess) == hit]  # only words consistent with the reply

What the code is doing, line by line:

  1. The secret has exactly hit matches with the guess, so any word that doesn't is eliminated.
  2. Minimising the largest group guarantees the most progress in the worst case.
  3. With 100 words, each round costs O(n²) comparisons.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Two candidates.
  • Words sharing many letters.
  • The first guess is the secret.

Complexity: O(n² · 6) per guess, at most about 10 guesses.

Medium 866. Prime Palindrome Google Math

Problem: Return the smallest prime palindrome ≥ n.

Example 1
Input: n = 6
Output: 7
Example 2
Input: n = 8
Output: 11

Constraints: 1 ≤ n ≤ 10⁸

Hint 1

Which palindromes can never be prime?

Hint 2

Generate palindromes directly instead of scanning all numbers.

From brute force to the pattern: Scanning upward from n and checking each number takes too long near 10⁷; generating palindromes skips almost everything.

Spot it: Every even-length palindrome is divisible by 11, so only 11 and odd-length palindromes matter. Build them from a root (left half) in increasing order and test primality with trial division up to √x.

Why not another pattern? Testing every number upward hits the 10⁷–10⁸ gap with no 8-digit prime palindromes: too slow.

Approach:

  1. If 8 ≤ n ≤ 11, return 11.
  2. For roots 1, 2, 3, …: x = int(root + reverse(root without its last digit)).
  3. Return the first x ≥ n that is prime.
class Solution:
    def primePalindrome(self, n: int) -> int:
        def is_prime(x):
            if x < 2:
                return False
            d = 2
            while d * d <= x:
                if x % d == 0:
                    return False
                d += 1
            return True

        if 8 <= n <= 11:
            return 11  # the only even-length prime palindrome
        root = 1
        while True:
            s = str(root)
            x = int(s + s[-2::-1])  # odd-length palindrome: 123 -> 12321
            if x >= n and is_prime(x):
                return x
            root += 1

What the code is doing, line by line:

  1. s[-2::-1] mirrors the root without repeating its last digit, giving odd length.
  2. Roots in increasing order produce odd-length palindromes in increasing order.
  3. Even-length palindromes are multiples of 11 (alternating digit sum is 0), so only 11 itself can be prime.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • n = 1 → 2.
  • n between 8 and 11 → 11.
  • Large n (answer 100030001).

Complexity: About O(√answer) per primality test over roughly 10⁴ roots.

Medium 1318. Minimum Flips to Make a OR b Equal to c Google Math

Problem: Return the minimum bit flips in a and b so that a | b == c.

Example 1
Input: a = 2, b = 6, c = 5
Output: 3
Explanation: After flips a = 1 , b = 4 , c = 5 such that (a OR b == c)
Example 2
Input: a = 4, b = 2, c = 7
Output: 1

Constraints: 1 ≤ a ≤ 10^9 · 1 ≤ b ≤ 10^9 · 1 ≤ c ≤ 10^9

Hint 1

Look at one bit position at a time.

Hint 2

What must a's and b's bits be for each value of c's bit?

From brute force to the pattern: Trying flip sets is exponential; bit-by-bit is O(31).

Spot it: Bits are independent → examine each bit position: c-bit 1 needs at least one 1; c-bit 0 needs both 0.

Why not another pattern? Trying flip combinations is exponential in the number of bits.

Approach:

  1. While any of a, b, c is non-zero: look at their lowest bits.
  2. c-bit 1: +1 if both a-bit and b-bit are 0. c-bit 0: + a-bit + b-bit.
  3. Shift all right.
class Solution:
    def minFlips(self, a: int, b: int, c: int) -> int:
        flips = 0
        while a or b or c:
            x, y, z = a & 1, b & 1, c & 1
            if z:
                flips += 1 if x == 0 and y == 0 else 0  # need at least one 1
            else:
                flips += x + y  # both must become 0
            a >>= 1
            b >>= 1
            c >>= 1
        return flips

What the code is doing, line by line:

  1. OR works bit by bit, so each position is solved independently.
  2. Turning one 0 into 1 suffices when c needs a 1; when c needs 0, every 1 must go.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Already equal → 0.
  • c = 0 (clear all bits).
  • Both a and b have a 1 where c has 0 (two flips).

Complexity: O(log max(a, b, c)) time, O(1) space.

Medium 1344. Angle Between Hands of a Clock Google Meta Amazon Microsoft Math

Problem: Return the smaller angle (degrees) between the hour and minute hands at hour:minutes.

Example 1
Input: hour = 12, minutes = 30
Output: 165
Example 2
Input: hour = 3, minutes = 30
Output: 75

Constraints: 1 ≤ hour ≤ 12 · 0 ≤ minutes ≤ 59

Hint 1

How many degrees does each hand move per minute?

Hint 2

Don't forget the hour hand moves between hours.

From brute force to the pattern: Constant time either way; precision of the formulas is the point.

Spot it: Clock arithmetic: compute each hand's angle from 12 o'clock, take the difference and its complement to 360.

Why not another pattern? Forgetting that the hour hand moves during the hour is the common mistake.

Approach:

  1. minute_angle = 6 · minutes.
  2. hour_angle = 30 · (hour % 12) + 0.5 · minutes.
  3. d = |h − m|; return min(d, 360 − d).
class Solution:
    def angleClock(self, hour: int, minutes: int) -> float:
        minute_angle = 6 * minutes  # 360 / 60
        hour_angle = 30 * (hour % 12) + 0.5 * minutes  # also moves while the minutes pass
        d = abs(hour_angle - minute_angle)
        return min(d, 360 - d)  # the smaller of the two angles

What the code is doing, line by line:

  1. hour % 12 maps 12 to 0.
  2. The hour hand moves 30° per 60 minutes = 0.5° per minute.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • 12:00 → 0.
  • Hands overlapping mid-hour.
  • Angle > 180 (take 360 − d).

Complexity: O(1).

Medium 1492. The kth Factor of n Start here Google Amazon Math

Problem: Return the k-th smallest divisor of n, or −1.

Example 1
Input: n = 12, k = 3
Output: 3
Explanation: Factors list is [1, 2, 3, 4, 6, 12], the 3rd factor is 3.
Example 2
Input: n = 7, k = 2
Output: 7
Explanation: Factors list is [1, 7], the 2nd factor is 7.

Constraints: 1 ≤ k ≤ n ≤ 1000

Hint 1

Divisors come in pairs.

Hint 2

List the ones up to √n and derive the rest.

From brute force to the pattern: Scanning 1..n is O(n); the paired scan is O(√n).

Spot it: Divisors pair up around √n: collect d ≤ √n in order, their partners n/d come in reverse order → O(√n).

Why not another pattern? Checking all 1..n is O(n) (fine for 1000, but the √n idea is what's asked).

Approach:

  1. small = [d for d ≤ √n if n % d == 0].
  2. large = [n // d for d in reversed(small) if d * d != n].
  3. Return the k-th of small + large, or −1.
class Solution:
    def kthFactor(self, n: int, k: int) -> int:
        small = []
        d = 1
        while d * d <= n:
            if n % d == 0:
                small.append(d)
            d += 1
        large = [n // d for d in reversed(small) if d * d != n]  # partners, increasing
        divisors = small + large
        return divisors[k - 1] if k <= len(divisors) else -1

What the code is doing, line by line:

  1. Each d ≤ √n that divides n has a partner n/d ≥ √n.
  2. A perfect square's root is its own partner, so it's not repeated.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • k larger than the divisor count → −1.
  • Perfect squares.
  • n prime.

Complexity: O(√n) time, O(√n) space for the divisors.

Medium 1680. Concatenation of Consecutive Binary Numbers Google Amazon Math

Problem: Concatenate the binary forms of 1..n; return the value mod 10⁹ + 7.

Example 1
Input: n = 1
Output: 1
Explanation: "1" in binary corresponds to the decimal value 1.
Example 2
Input: n = 3
Output: 27
Explanation: In binary, 1, 2, and 3 corresponds to "1", "10", and "11". After concatenating them, we have "11011", which corresponds to the decimal value 27.

Constraints: 1 ≤ n ≤ 10⁵

Hint 1

Appending k bits to a number is a left shift by k.

Hint 2

When does the bit length of i increase?

From brute force to the pattern: String building is O(n log n) and needs big-integer conversion; shifting with mod is O(n).

Spot it: Appending i's bits means value = (value << bits(i)) | i. The bit length grows by one at each power of two (bit manipulation).

Why not another pattern? Building the binary string is O(n log n) characters and a huge number.

Approach:

  1. bits = 0; for i in 1..n: if i is a power of two (i & (i − 1) == 0), bits += 1.
  2. value = ((value << bits) | i) % MOD.
class Solution:
    def concatenatedBinary(self, n: int) -> int:
        MOD = 10**9 + 7
        value = 0
        bits = 0
        for i in range(1, n + 1):
            if i & (i - 1) == 0:
                bits += 1  # a power of two: one more binary digit
            value = ((value << bits) | i) % MOD  # append i's binary digits
        return value

What the code is doing, line by line:

  1. i & (i − 1) == 0 is true exactly for powers of two.
  2. Shifting left by bits makes room for i, and OR writes it in.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • n = 1 → 1.
  • Powers of two.
  • Large n (mod).

Complexity: O(n) time, O(1) space.

Medium 1922. Count Good Numbers Google Meta Math

Problem: Count digit strings of length n (up to 10¹⁵) with even digits at even indices and prime digits at odd indices (mod 10⁹ + 7).

Example 1
Input: n = 1
Output: 5
Explanation: The good numbers of length 1 are "0", "2", "4", "6", "8".
Example 2
Input: n = 4
Output: 400

Constraints: 1 ≤ n ≤ 10¹⁵

Hint 1

How many choices does each position have?

Hint 2

Multiply them with fast exponentiation.

From brute force to the pattern: n multiplications vs log n.

Spot it: Positions are independent: multiply choices. With n up to 10¹⁵, use fast modular exponentiation.

Why not another pattern? Multiplying one position at a time is O(n).

Approach:

  1. even = (n + 1) // 2, odd = n // 2.
  2. Return pow(5, even, MOD) · pow(4, odd, MOD) % MOD.
class Solution:
    def countGoodNumbers(self, n: int) -> int:
        MOD = 10**9 + 7
        even_slots = (n + 1) // 2  # indices 0, 2, 4, ...: digits 0, 2, 4, 6, 8
        odd_slots = n // 2  # indices 1, 3, 5, ...: digits 2, 3, 5, 7
        return pow(5, even_slots, MOD) * pow(4, odd_slots, MOD) % MOD

What the code is doing, line by line:

  1. Each even index has 5 choices and each odd index 4, independently.
  2. Python's three-argument pow does binary exponentiation mod MOD.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • n = 1 → 5.
  • Huge n.
  • n = 4 → 400.

Complexity: O(log n) time, O(1) space.

Hard 3312. Sorted GCD Pair Queries Google Amazon ArrayMath

Problem: Sort the GCDs of all pairs; answer queries for the value at given indices.

Example 1
Input: nums = [2,3,4], queries = [0,2,2]
Output: [1,2,2]
Explanation: gcdPairs = [gcd(nums[0], nums[1]), gcd(nums[0], nums[2]), gcd(nums[1], nums[2])] = [1, 2, 1]. After sorting in ascending order, gcdPairs = [1, 1, 2]. So, the answer is [gcdPairs[queries[0]], gcdPairs[queries[1]], gcdPairs[queries[2]]] = [1, 2, 2].
Example 2
Input: nums = [4,4,2,1], queries = [5,3,1,0]
Output: [4,2,1,1]
Explanation: gcdPairs sorted in ascending order is [1, 1, 1, 2, 2, 4].

Constraints: 2 ≤ n == nums.length ≤ 10⁵ · 1 ≤ nums[i] ≤ 5 * 10⁴ · 1 ≤ queries.length ≤ 10⁵ · 0 ≤ queries[i] < n * (n - 1) / 2

Hint 1

Count how many pairs have each gcd value instead of listing them.

Hint 2

Pairs where both numbers are multiples of g is easy to count. How do you turn that into gcd exactly g?

Hint 3

Use prefix sums over the gcd values and binary search for each query.

From brute force to the pattern: All pairs: O(n²). Counting by multiples: O(M log M).

Spot it: There are up to 5·10⁹ pairs, so count them by value. Pairs whose gcd is a multiple of g are C(m_g, 2) where m_g counts multiples of g. Subtract the counts for 2g, 3g, … (inclusion–exclusion from the top). Then prefix sums over g and a binary search per query.

Why not another pattern? Computing all pair GCDs is O(n²).

Approach:

  1. freq[v] = occurrences of v; m_g = Σ freq[g · t].
  2. From g = max down to 1: exact[g] = C(m_g, 2) − Σ exact[t · g] for t ≥ 2.
  3. prefix[g] = pairs with gcd ≤ g; answer q by bisect_right(prefix, q).
from bisect import bisect_right
from itertools import accumulate

class Solution:
    def gcdValues(self, nums: List[int], queries: List[int]) -> List[int]:
        top = max(nums)
        freq = [0] * (top + 1)
        for x in nums:
            freq[x] += 1
        exact = [0] * (top + 1)  # pairs whose gcd is exactly g
        for g in range(top, 0, -1):
            m = sum(freq[g::g])  # numbers divisible by g
            exact[g] = m * (m - 1) // 2 - sum(exact[2 * g::g])  # remove pairs with a larger gcd
        prefix = list(accumulate(exact))  # prefix[g]: pairs with gcd <= g
        return [bisect_right(prefix, q) for q in queries]  # first g whose prefix exceeds q

What the code is doing, line by line:

  1. Both numbers of a pair are multiples of g exactly when g divides their gcd.
  2. Going from large g to small, the counts for multiples of g are already exact, so subtracting them leaves gcd exactly g.
  3. prefix[g] counts pairs at sorted positions 0..prefix[g] − 1; the answer for index q is the first g with prefix[g] > q.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Repeated values.
  • All values coprime (every gcd is 1).
  • Two elements.

Complexity: O(M log M + q log M) time (harmonic sums over M = max(nums)), O(M) space.

Medium 3513. Number of Unique XOR Triplets I Google Amazon Microsoft ArrayMath

Problem: nums is a permutation of 1..n. Count distinct values of nums[i] ^ nums[j] ^ nums[k] with i ≤ j ≤ k.

Example 1
Input: nums = [1,2]
Output: 2
Explanation: The possible XOR triplet values are: (0, 0, 0) → 1 XOR 1 XOR 1 = 1 (0, 0, 1) → 1 XOR 1 XOR 2 = 2 (0, 1, 1) → 1 XOR 2 XOR 2 = 1 (1, 1, 1) → 2 XOR 2 XOR 2 = 2 The unique XOR values are {1, 2}, so the output is 2.
Example 2
Input: nums = [3,1,2]
Output: 4
Explanation: The possible XOR triplet values include: (0, 0, 0) → 3 XOR 3 XOR 3 = 3 (0, 0, 1) → 3 XOR 3 XOR 1 = 1 (0, 0, 2) → 3 XOR 3 XOR 2 = 2 (0, 1, 2) → 3 XOR 1 XOR 2 = 0 The unique XOR values are {0, 1, 2, 3}, so the output is 4.

Constraints: 1 ≤ n == nums.length ≤ 10⁵ · 1 ≤ nums[i] ≤ n · nums is a permutation of integers from 1 to n.

Hint 1

Can a triplet use the same index more than once? What does x ^ y ^ y give?

Hint 2

Which values below the next power of two can you build from 1..n?

From brute force to the pattern: Triple loop: O(n³); the observation is constant time.

Spot it: A bit-manipulation observation: indices may repeat, so any single value x = x ^ y ^ y is reachable, and with 1..n available every number below 2^(bit length of n) can be formed for n ≥ 3. For n ≤ 2, the answer is n.

Why not another pattern? All triples are O(n³); even pairs-plus-one is O(n²).

Approach:

  1. If n ≤ 2, return n.
  2. Otherwise return 1 << n.bit_length().
class Solution:
    def uniqueXorTriplets(self, nums: List[int]) -> int:
        n = len(nums)
        if n <= 2:
            return n  # n = 1: {1}; n = 2: {1, 2}
        return 1 << n.bit_length()  # every value from 0 to 2^bits - 1 is reachable

What the code is doing, line by line:

  1. XOR never sets a bit above the highest bit of n, so values stay below 2^bits.
  2. With 1, 2, 3 and the top power of two available, every combination below 2^bits is reachable (0 = 1 ^ 2 ^ 3).
  3. For n ≤ 2 there aren't enough values to reach the rest.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • n = 1 → 1.
  • n = 2 → 2.
  • n a power of two.

Complexity: O(1) time and space.

Medium 3702. Longest Subsequence With Non-Zero Bitwise XOR Google Array

Problem: Return the length of the longest subsequence whose XOR is non-zero (0 if none).

Example 1
Input: nums = [1,2,3]
Output: 2
Explanation: One longest subsequence is [2, 3]. The bitwise XOR is computed as 2 XOR 3 = 1, which is non-zero.
Example 2
Input: nums = [2,3,4]
Output: 3
Explanation: The longest subsequence is [2, 3, 4]. The bitwise XOR is computed as 2 XOR 3 XOR 4 = 5, which is non-zero.

Constraints: 1 ≤ nums.length ≤ 10⁵ · 0 ≤ nums[i] ≤ 10⁹

Hint 1

What if the XOR of the whole array is already non-zero?

Hint 2

If it's zero, what happens when you remove one element?

From brute force to the pattern: Checking subsequences is exponential; three cases cover everything.

Spot it: XOR reasoning: if the whole array's XOR is non-zero, take everything. If it's zero, removing any non-zero element x leaves XOR x ≠ 0. Only an all-zero array has no answer.

Why not another pattern? Subsequence DP over XOR values is far too big.

Approach:

  1. total = XOR of all.
  2. total ≠ 0 → n; all zeros → 0; else n − 1.
from functools import reduce
from operator import xor

class Solution:
    def longestSubsequence(self, nums: List[int]) -> int:
        if reduce(xor, nums) != 0:
            return len(nums)  # the whole array works
        if not any(nums):
            return 0  # every subsequence XORs to 0
        return len(nums) - 1  # removing one non-zero x leaves XOR x

What the code is doing, line by line:

  1. XOR of everything except x equals total ^ x = x when total = 0.
  2. A subsequence of only zeros always XORs to 0.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • All zeros → 0.
  • One non-zero element.
  • Total XOR is zero.

Complexity: O(n) time, O(1) space.

Medium 1823. Find the Winner of the Circular Game Meta Amazon Microsoft Math

Problem: n friends in a circle; repeatedly count k and remove that friend. Return the winner (1-indexed).

Example 1
Input: n = 5, k = 2
Output: 3
Explanation: Here are the steps of the game: 1) Start at friend 1. 2) Count 2 friends clockwise, which are friends 1 and 2. 3) Friend 2 leaves the circle. Next start is friend 3. 4) Count 2 friends clockwise, which are friends 3 and 4. 5) Friend 4 leaves the circle. Next start is friend 5. 6) Count 2 friends clockwise, which are friends 5 and 1. 7) Friend 1 leaves the circle. Next start is friend 3. 8) Count 2 friends clockwise, which are friends 3 and 5. 9) Friend 5 leaves the circle. Only friend 3 is left, so they are the winner.
Example 2
Input: n = 6, k = 5
Output: 1
Explanation: The friends leave in this order: 5, 4, 6, 2, 3. The winner is friend 1.

Constraints: 1 ≤ k ≤ n ≤ 500

Hint 1

After one removal, the game is the same with one fewer person. How are positions renumbered?

Hint 2

Write the Josephus recurrence.

From brute force to the pattern: List simulation is O(n²); the recurrence is O(n).

Spot it: The Josephus problem. After the first removal the game restarts with n − 1 people, shifted by k, so the winner's position follows the recurrence J(i) = (J(i − 1) + k) mod i.

Why not another pattern? Simulating with a list is O(n²) (or O(nk) with a queue).

Approach:

  1. pos = 0 (with one person, the winner is at index 0).
  2. For i from 2 to n: pos = (pos + k) % i.
  3. Return pos + 1.
class Solution:
    def findTheWinner(self, n: int, k: int) -> int:
        pos = 0  # winner's 0-based position with 1 person
        for i in range(2, n + 1):
            pos = (pos + k) % i  # adding a person shifts everyone by k
        return pos + 1

What the code is doing, line by line:

  1. With i people, removing the k-th leaves i − 1 people starting just after it, i.e. everyone's position shifted by k.
  2. Undoing that shift from 1 person up to n gives the winner's original seat.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • k = 1 → n.
  • n = 1 → 1.
  • k larger than n.

Complexity: O(n) time, O(1) space.

Medium 318. Maximum Product of Word Lengths Amazon StringArray

Problem: Return the maximum len(a) · len(b) over pairs of words with no common letters.

Example 1
Input: words = ["abcw","baz","foo","bar","xtfn","abcdef"]
Output: 16
Explanation: The two words can be "abcw", "xtfn".
Example 2
Input: words = ["a","ab","abc","d","cd","bcd","abcd"]
Output: 4
Explanation: The two words can be "ab", "cd".

Constraints: 2 ≤ words.length ≤ 1000 · 1 ≤ words[i].length ≤ 1000 · words[i] consists only of lowercase English letters.

Hint 1

How can you test "no common letters" in O(1)?

Hint 2

Use a 26-bit mask per word.

From brute force to the pattern: Pairwise string checks are O(n² L); masks make each check O(1).

Spot it: Represent each word's letters as a bitmask; "no common letters" becomes mask_a & mask_b == 0, an O(1) check.

Why not another pattern? Comparing letter sets pairwise as strings is O(n² · L).

Approach:

  1. Mask per word (keep the longest word per mask).
  2. For every pair of masks with a & b == 0, update the product.
class Solution:
    def maxProduct(self, words: List[str]) -> int:
        longest = {}  # letter mask -> longest word length with exactly those letters
        for w in words:
            mask = 0
            for ch in w:
                mask |= 1 << (ord(ch) - 97)
            longest[mask] = max(longest.get(mask, 0), len(w))
        best = 0
        items = list(longest.items())
        for i, (m1, l1) in enumerate(items):
            for m2, l2 in items[i + 1:]:
                if m1 & m2 == 0:
                    best = max(best, l1 * l2)  # no shared letters
        return best

What the code is doing, line by line:

  1. Words with the same letter set only need their longest representative.
  2. A bitwise AND is zero exactly when no letter is shared.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • No valid pair → 0.
  • Words with repeated letters.
  • Many words with the same letters.

Complexity: O(Σ L + m²) time for m distinct masks, O(m) space.

Medium 3514. Number of Unique XOR Triplets II Amazon ArrayHash Set

Problem: Count distinct values of nums[i] ^ nums[j] ^ nums[k] with i ≤ j ≤ k.

Example 1
Input: nums = [1,3]
Output: 2
Explanation: The possible XOR triplet values are: (0, 0, 0) → 1 XOR 1 XOR 1 = 1 (0, 0, 1) → 1 XOR 1 XOR 3 = 3 (0, 1, 1) → 1 XOR 3 XOR 3 = 1 (1, 1, 1) → 3 XOR 3 XOR 3 = 3 The unique XOR values are {1, 3}. Thus, the output is 2.
Example 2
Input: nums = [6,7,8,9]
Output: 4
Explanation: The possible XOR triplet values are {6, 7, 8, 9}. Thus, the output is 4.

Constraints: 1 ≤ nums.length ≤ 1500 · 1 ≤ nums[i] ≤ 1500

Hint 1

How large can a XOR of values up to 1500 be?

Hint 2

Compute all pair XORs first, then combine with a third value.

From brute force to the pattern: Triple loops: O(n³); two set steps: O(V²).

Spot it: XORs of values ≤ 1500 stay below 2048, so sets of results are tiny. Build the set of pair XORs (i ≤ j, so x ^ x = 0 is included), then XOR each with every value — bit manipulation with small sets instead of triple loops over indices.

Why not another pattern? Triple loops over 1500 elements are 5·10⁸.

Approach:

  1. vals = set(nums).
  2. pairs = {a ^ b for a, b in vals} (including a = b).
  3. triples = {p ^ c for p in pairs for c in vals}; return its size.
class Solution:
    def uniqueXorTriplets(self, nums: List[int]) -> int:
        vals = set(nums)
        pairs = {a ^ b for a in vals for b in vals}  # i <= j allows a == b (giving 0)
        triples = {p ^ c for p in pairs for c in vals}  # add the third element
        return len(triples)

What the code is doing, line by line:

  1. Only distinct values matter, and indices may repeat, so pairs of values (including equal ones) cover all i ≤ j.
  2. Both sets have at most 2048 elements, so the final step is about 3 million operations.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • One element → 1.
  • Duplicates.
  • Values that are powers of two.

Complexity: O(V² + 2048 · V) time for V distinct values, O(2048) space.

Medium 3644. Maximum K to Sort a Permutation Amazon Array

Problem: Swaps are allowed only between values whose AND equals k. Return the largest k that lets you sort the permutation.

Example 1
Input: nums = [0,3,2,1]
Output: 1
Explanation: Choose k = 1. Swapping nums[1] = 3 and nums[3] = 1 is allowed since nums[1] AND nums[3] == 1, resulting in a sorted permutation: [0, 1, 2, 3].
Example 2
Input: nums = [0,1,3,2]
Output: 2
Explanation: Choose k = 2. Swapping nums[2] = 3 and nums[3] = 2 is allowed since nums[2] AND nums[3] == 2, resulting in a sorted permutation: [0, 1, 2, 3].

Constraints: 1 ≤ n == nums.length ≤ 10⁵ · 0 ≤ nums[i] ≤ n - 1 · nums is a permutation of integers from 0 to n - 1.

Hint 1

Which elements have to be swapped at all?

Hint 2

What does a swap's AND say about the bits of the values involved?

From brute force to the pattern: Testing each k by building swap graphs is slow; the AND of misplaced values is O(n).

Spot it: Every misplaced value must take part in a swap, and a swap's AND keeps only bits shared by both values, so k can't have a bit missing from any misplaced value: k ≤ AND of misplaced values. That bound is always achievable, so the answer is a one-line bit-manipulation formula.

Why not another pattern? Trying every k with a graph check is O(n²) or worse.

Approach:

  1. AND together every nums[i] with nums[i] != i.
  2. Return it (0 if nothing is misplaced).
from functools import reduce
from operator import and_

class Solution:
    def sortPermutation(self, nums: List[int]) -> int:
        misplaced = [x for i, x in enumerate(nums) if x != i]
        return reduce(and_, misplaced) if misplaced else 0  # bits every moved value shares

What the code is doing, line by line:

  1. A value that must move is swapped at least once, so every bit of k is in that value.
  2. With k equal to the common bits of all misplaced values, they can be sorted (checked against brute force on small cases).

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Already sorted → 0.
  • Two values swapped.
  • Misplaced values with no common bits → 0.

Complexity: O(n) time, O(1) space.

Medium 3047. Find the Largest Area of Square Inside Two Rectangles Cisco ArrayMath

Problem: Return the largest area of a square that fits inside the intersection of at least two of the axis-aligned rectangles.

Example 1
Input: bottomLeft = [[1,1],[2,2],[3,1]], topRight = [[3,3],[4,4],[6,6]]
Output: 1
Explanation: A square with side length 1 can fit inside either the intersecting region of rectangles 0 and 1 or the intersecting region of rectangles 1 and 2. Hence the maximum area is 1. It can be shown that a square with a greater side length can not fit inside any intersecting region of two rectangles.
Example 2
Input: bottomLeft = [[1,1],[1,3],[1,5]], topRight = [[5,5],[5,7],[5,9]]
Output: 4
Explanation: A square with side length 2 can fit inside either the intersecting region of rectangles 0 and 1 or the intersecting region of rectangles 1 and 2. Hence the maximum area is 2 * 2 = 4. It can be shown that a square with a greater side length can not fit inside any intersecting region of two rectangles.

Constraints: n == bottomLeft.length == topRight.length · 2 ≤ n ≤ 10³ · bottomLeft[i].length == topRight[i].length == 2 · 1 ≤ bottomLeft[i][0], bottomLeft[i][1] ≤ 10⁷ · 1 ≤ topRight[i][0], topRight[i][1] ≤ 10⁷ · bottomLeft[i][0] < topRight[i][0] · bottomLeft[i][1] < topRight[i][1]

Hint 1

Compute the intersection of two axis-aligned rectangles.

Hint 2

The largest square inside a rectangle has side min(width, height).

From brute force to the pattern: All pairs is already the intended O(n²) solution.

Spot it: Geometry: the intersection of two axis-aligned rectangles is a rectangle with width min(right) − max(left), height likewise. Its largest square has side min(w, h).

Why not another pattern? Grids or sweeps are unnecessary; with n ≤ 1000, checking all pairs is fast.

Approach:

  1. For every pair: w = min(c) − max(a), h = min(d) − max(b).
  2. side = min(w, h); keep the largest positive side.
  3. Return side².
class Solution:
    def largestSquareArea(self, bottomLeft: List[List[int]], topRight: List[List[int]]) -> int:
        n = len(bottomLeft)
        best = 0
        for i in range(n):
            for j in range(i + 1, n):
                w = min(topRight[i][0], topRight[j][0]) - max(bottomLeft[i][0], bottomLeft[j][0])
                h = min(topRight[i][1], topRight[j][1]) - max(bottomLeft[i][1], bottomLeft[j][1])
                best = max(best, min(w, h))  # negative when they don't overlap
        return best * best

What the code is doing, line by line:

  1. Overlap in each axis is "smaller right edge minus larger left edge".
  2. Intersections of more rectangles are smaller, so pairs are enough.
  3. A non-positive side means no square.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • No overlaps → 0.
  • Touching edges (side 0).
  • One rectangle inside another.

Complexity: O(n²) time, O(1) space.

Medium 3648. Minimum Sensors to Cover Grid Cisco Math

Problem: A sensor covers cells within Chebyshev distance k. Return the fewest sensors that cover an n × m grid.

Example 1
Input: n = 5, m = 5, k = 1
Output: 4
Explanation: Placing sensors at positions (0, 3), (1, 0), (3, 3), and (4, 1) ensures every cell in the grid is covered. Thus, the answer is 4.
Example 2
Input: n = 2, m = 2, k = 2
Output: 1
Explanation: With k = 2, a single sensor can cover the entire 2 * 2 grid regardless of its position. Thus, the answer is 1.

Constraints: 1 ≤ n ≤ 10³ · 1 ≤ m ≤ 10³ · 0 ≤ k ≤ 10³

Hint 1

What shape does one sensor cover?

Hint 2

Treat rows and columns separately.

From brute force to the pattern: Greedy placement gives the same answer slowly; the formula is constant time.

Spot it: Chebyshev distance k is a (2k + 1)-wide square, and rows and columns are independent → tile each dimension: a math formula.

Why not another pattern? Placing sensors greedily cell by cell gives the same count but more work.

Approach:

  1. side = 2k + 1.
  2. Return ceil(n / side) · ceil(m / side).
class Solution:
    def minSensors(self, n: int, m: int, k: int) -> int:
        side = 2 * k + 1  # width of the square one sensor covers
        return (-(-n // side)) * (-(-m // side))  # ceil in each direction

What the code is doing, line by line:

  1. Covering a row of length n with intervals of length side needs ceil(n / side).
  2. A square cover is the product of a row cover and a column cover, and you can't do better since each sensor covers at most side rows and side columns.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • k = 0 → n · m.
  • k large → 1.
  • One row.

Complexity: O(1).

Hard 2081. Sum of k-Mirror Numbers Cisco Math

Problem: Return the sum of the n smallest numbers that are palindromes in base 10 and in base k.

Example 1
Input: k = 2, n = 5
Output: 25
Explanation: The 5 smallest 2-mirror numbers and their representations in base-2 are listed as follows: base-10 base-2 1 1 3 11 5 101 7 111 9 1001 Their sum = 1 + 3 + 5 + 7 + 9 = 25.
Example 2
Input: k = 3, n = 7
Output: 499
Explanation: The 7 smallest 3-mirror numbers are and their representations in base-3 are listed as follows: base-10 base-3 1 1 2 2 4 11 8 22 121 11111 151 12121 212 21212 Their sum = 1 + 2 + 4 + 8 + 121 + 151 + 212 = 499.

Constraints: 2 ≤ k ≤ 9 · 1 ≤ n ≤ 30

Hint 1

Which condition is easier to generate numbers for directly?

Hint 2

Generate base-10 palindromes in increasing order and test them in base k.

From brute force to the pattern: Checking every integer is hopeless; generating palindromes visits only about √X candidates.

Spot it: Checking every integer is too slow (the 30th can be in the billions). Generate only base-10 palindromes, in increasing order, from their first halves, and test the base-k representation — number-base arithmetic.

Why not another pattern? Scanning all integers up to ~10¹⁰ is far too slow.

Approach:

  1. For each length L = 1, 2, …: for each half from 10^(h−1) to 10^h − 1, build the palindrome (odd lengths drop the middle repeat).
  2. Convert to base k; if it's a palindrome, add it.
  3. Stop after n.
class Solution:
    def kMirror(self, k: int, n: int) -> int:
        def base_k_palindrome(x):
            digits = []
            while x:
                digits.append(x % k)
                x //= k
            return digits == digits[::-1]

        total = found = 0
        length = 1
        while found < n:
            half = (length + 1) // 2
            for first in range(10 ** (half - 1), 10 ** half):  # increasing halves -> increasing palindromes
                s = str(first)
                pal = int(s + s[::-1][length % 2:])  # mirror (skip the middle digit for odd length)
                if base_k_palindrome(pal):
                    total += pal
                    found += 1
                    if found == n:
                        break
            length += 1
        return total

What the code is doing, line by line:

  1. For a fixed length, palindromes increase with their first half, so they're produced in order.
  2. s[::-1][length % 2:] drops the repeated middle digit for odd lengths.
  3. Base-10 palindromes are rare (about √N up to N), so the search is fast.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Single-digit numbers (all palindromes).
  • Large k.
  • n = 1.

Complexity: About O(√X · log X) for the largest answer X.

Medium 779. K-th Symbol in Grammar Microsoft Math

Problem: Row 1 is 0; each row replaces 0 with 01 and 1 with 10. Return the k-th symbol of row n.

Example 1
Input: n = 1, k = 1
Output: 0
Explanation: row 1: 0
Example 2
Input: n = 2, k = 1
Output: 0
Explanation: row 1: 0 row 2: 01

Constraints: 1 ≤ n ≤ 30 · 1 ≤ k ≤ 2n ⁻ ¹

Hint 1

How is the symbol at position i related to its parent?

Hint 2

Count how many times it flips on the way from the root.

From brute force to the pattern: Building rows is O(2ⁿ); counting bits is O(log k).

Spot it: Symbol k (0-indexed k − 1) descends from its parent at (k − 1) // 2, flipped when it's a right child (odd index). Following the bits of k − 1 from the top, it flips once per 1-bit → bit manipulation.

Why not another pattern? Building row n needs 2^(n−1) symbols.

Approach:

  1. Return bin(k − 1).count('1') % 2.
class Solution:
    def kthGrammar(self, n: int, k: int) -> int:
        return bin(k - 1).count("1") % 2  # one flip for every right turn on the way down

What the code is doing, line by line:

  1. A left child keeps its parent's symbol, a right child flips it.
  2. The path from the root to position k − 1 is given by its binary digits; each 1 is a right turn.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • k = 1 → 0.
  • n = 1.
  • Last position of a row.

Complexity: O(log k) time, O(1) space.

Medium 2571. Minimum Operations to Reduce an Integer to 0 Microsoft Math

Problem: Add or subtract any power of 2 per operation. Return the fewest operations to make n zero.

Example 1
Input: n = 39
Output: 3
Explanation: We can do the following operations: - Add 2⁰ = 1 to n, so now n = 40. - Subtract 2³ = 8 from n, so now n = 32. - Subtract 2⁵ = 32 from n, so now n = 0. It can be shown that 3 is the minimum number of operations we need to make n equal to 0.
Example 2
Input: n = 54
Output: 3
Explanation: We can do the following operations: - Add 2¹ = 2 to n, so now n = 56. - Add 2³ = 8 to n, so now n = 64. - Subtract 2⁶ = 64 from n, so now n = 0. So the minimum number of operations is 3.

Constraints: 1 ≤ n ≤ 10⁵

Hint 1

Look at n in binary.

Hint 2

When is adding a power of two better than subtracting one?

From brute force to the pattern: BFS over integers is slow; the bit scan is O(log n).

Spot it: A bit manipulation greedy: scan from the lowest bit. A single 1 (next bit 0) costs one subtraction. A run of 1s (next bit also 1) is cheaper to clear by adding 1, which turns the run into one carry. This builds the non-adjacent form, which has the fewest non-zero digits.

Why not another pattern? BFS over values works but is far slower and unnecessary.

Approach:

  1. While n: if the lowest bit is 1: if the next bit is also 1, n += 1, else n −= 1; count an operation.
  2. Shift right.
class Solution:
    def minOperations(self, n: int) -> int:
        ops = 0
        while n:
            if n & 1:
                if n & 2:
                    n += 1  # a run of 1s: one carry clears the whole run
                else:
                    n -= 1  # a lone 1: just subtract it
                ops += 1
            n >>= 1
        return ops

What the code is doing, line by line:

  1. Adding 1 to ...0111 gives ...1000: one operation replaces the run.
  2. A lone 1 can't be merged with anything, so subtracting it is best.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • Power of two → 1.
  • All ones (2^k − 1) → 2.
  • n = 1.

Complexity: O(log n) time, O(1) space.

Hard 829. Consecutive Numbers Sum Microsoft Math

Problem: Count the ways to write n as a sum of one or more consecutive positive integers.

Example 1
Input: n = 5
Output: 2
Explanation: 5 = 2 + 3
Example 2
Input: n = 9
Output: 3
Explanation: 9 = 4 + 5 = 2 + 3 + 4

Constraints: 1 ≤ n ≤ 10⁹

Hint 1

Write the sum of k consecutive numbers starting at x.

Hint 2

For which k does an integer x ≥ 1 exist?

From brute force to the pattern: All start/length pairs are O(n²); iterating k is O(√n).

Spot it: Math: a run of k numbers starting at x sums to k·x + k(k − 1)/2. For each length k, check whether n − k(k − 1)/2 is a positive multiple of k. Only k up to about √(2n) can fit.

Why not another pattern? Trying every start and length is O(n²).

Approach:

  1. For k = 1, 2, … while k(k − 1)/2 < n:
  2. If (n − k(k − 1)/2) % k == 0, count it.
class Solution:
    def consecutiveNumbersSum(self, n: int) -> int:
        ways = 0
        k = 1
        while k * (k - 1) // 2 < n:  # the smallest run of length k is 1 + 2 + ... + k
            if (n - k * (k - 1) // 2) % k == 0:
                ways += 1  # x = (n - k(k-1)/2) / k is a positive integer
            k += 1
        return ways

What the code is doing, line by line:

  1. x = (n − k(k − 1)/2) / k must be a positive integer.
  2. Once k(k − 1)/2 ≥ n, x would be ≤ 0, so the loop stops.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • n = 1 → 1.
  • Powers of two (only the number itself).
  • Large n.

Complexity: O(√n) time, O(1) space.

Medium 477. Total Hamming Distance Apple Array

Problem: Return the sum of Hamming distances over all pairs of numbers.

Example 1
Input: nums = [4,14,2]
Output: 6
Explanation: In binary representation, the 4 is 0100, 14 is 1110, and 2 is 0010 (just showing the four bits relevant in this case). The answer will be: HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6.
Example 2
Input: nums = [4,14,4]
Output: 4

Constraints: 1 ≤ nums.length ≤ 10⁴ · 0 ≤ nums[i] ≤ 10⁹ · The answer for the given input will fit in a 32-bit integer.

Hint 1

Look at a single bit position across all numbers.

Hint 2

How many pairs differ at that bit?

From brute force to the pattern: All pairs: O(32 n²); per-bit counting: O(32 n).

Spot it: Bits are independent → look at one bit position at a time: with c ones among n numbers, exactly c · (n − c) pairs differ at that bit.

Why not another pattern? Comparing all pairs is O(n² · 32).

Approach:

  1. For each of 32 bits: c = numbers with that bit set.
  2. Add c · (n − c).
class Solution:
    def totalHammingDistance(self, nums: List[int]) -> int:
        n = len(nums)
        total = 0
        for b in range(32):
            ones = sum((x >> b) & 1 for x in nums)  # numbers with bit b set
            total += ones * (n - ones)  # each (one, zero) pair differs here
        return total

What the code is doing, line by line:

  1. A pair contributes 1 at bit b exactly when one number has it and the other doesn't.
  2. Summing over bits counts every differing bit of every pair.

Dry run: use the Step through the solution player under the code. It runs this exact code on Example 1 and shows every line with the variables at that moment.

Edge cases to test:

  • All equal → 0.
  • Two numbers.
  • Zeros.

Complexity: O(32 · n) time, O(1) space.