Bird
Raised Fist0
Interview Prepbit-manipulationmediumAmazonGoogleFacebook

Maximum XOR of Two Numbers

Choose your preparation mode4 modes available
▶
Steps
setup

Initialize Trie and Prepare to Insert First Number (3)

Create an empty trie and prepare to insert the first number, 3, processing its bits from the 31st (MSB) to the 0th (LSB).

💡 Initializing the trie is essential to store all numbers bit-by-bit for efficient XOR queries.
Line:trie = Trie() num = 3 trie.insert(num)
💡 The trie starts empty and will be built by inserting each number's bits from MSB to LSB.
📊
Maximum XOR of Two Numbers - Watch the Algorithm Execute, Step by Step
Watching the bitwise trie construction and traversal visually reveals how XOR maximization works at the bit level, which is hard to grasp from code alone.
Step 1/18
·Active fill★Answer cell
Check MSB of 3
A
0
1
1
=3
B
💡 Starting insertion of number 3 from MSB to LSB
Insert bit 0 at position 31
A
0
1
1
=3
B
💡 Created new trie node for bit 0 at MSB
Insert bit 0 at position 30
A
0
1
1
=3
B
💡 Extended trie path with bit 0 at position 30
Insert bit 1 at position 1
A
0
1
1
=3
B
💡 Created branch for bit 1 at position 1
Insert bit 1 at position 0
A
0
1
1
=3
B
💡 Completed insertion of number 3
Check MSB of 10
A
0
1
0
1
0
=10
B
💡 Traverse existing trie node for bit 0 at MSB
Insert bit 1 at position 3
A
0
1
0
1
0
=10
B
💡 Created new trie node for bit 1 at bit 3
Check bit 31 of 5 and trie
A
0
1
0
1
=5
B
=000000000000000000000000000000000
────────────────
=
0
0
0
0
0
0
0
0
=0
💡 No opposite bit 1 at MSB, follow bit 0 path
Set bit 4 in max_xor
A
0
1
0
1
=5
B
=000010000000000000000000000000000
────────────────
=
0
0
0
0
0
0
0
0
=16
💡 Opposite bit found, XOR bit set to 1 at position 4
Set bit 3 in max_xor
A
0
1
0
1
=5
B
=000110000000000000000000000000000
────────────────
=
0
0
0
0
0
0
0
0
=24
💡 Opposite bit found, XOR bit set to 1 at position 3
Set bit 0 in max_xor
A
0
1
0
1
=5
B
=000110000000000000000000000000000
────────────────
=
0
0
0
0
0
0
0
1
=25
💡 Opposite bit found, XOR bit set to 1 at position 0
Update max_xor to 25
A
0
1
0
1
=5
B
💡 max_xor updated to 25 after traversal
Set bit 4 in max_xor
A
0
1
1
0
0
1
=25
B
=000000000000000000000000000000000
────────────────
=
0
0
0
0
0
0
0
0
=16
💡 Opposite bit found, XOR bit set to 1 at position 4
Set bit 3 in max_xor
A
0
1
1
0
0
1
=25
B
=000000000000000000000000000000000
────────────────
=
0
0
0
0
0
0
0
0
=24
💡 Opposite bit found, XOR bit set to 1 at position 3
Set bit 0 in max_xor
A
0
1
1
0
0
1
=25
B
=000000000000000000000000000000000
────────────────
=
0
0
0
0
0
0
0
1
=25
💡 Opposite bit found, XOR bit set to 1 at position 0
max_xor remains 25
A
0
1
1
0
0
1
=25
B
💡 max_xor unchanged after traversal
Set bits 4 and 3 in max_xor
A
0
1
0
1
=5
B
=000010000000000000000000000000000
────────────────
=
0
0
0
0
0
0
0
0
=28
💡 New max_xor 28 found by choosing opposite bits
Return max_xor = 28
A
0
1
1
1
0
0
=28
B
────────────
=
0
1
1
1
0
0
=28
💡 Maximum XOR of two numbers in input is 28

Key Takeaways

✓ Building a trie of bits from MSB to LSB allows efficient representation of all numbers for XOR queries.

This insight is hard to see from code alone because the trie structure and bitwise operations are abstract without visualization.

✓ During traversal, choosing the opposite bit path whenever possible maximizes the XOR bitwise.

Visualizing this choice at each bit clarifies why XOR is maximized by picking opposite bits.

✓ The maximum XOR is found by comparing XOR values obtained from traversing the trie for each number.

Seeing the max_xor update step-by-step shows how the algorithm finds the global maximum.

Practice

(1/5)
1. You are given an array of integers and a range [low, high]. You need to count the number of pairs (i, j) with i < j such that the XOR of nums[i] and nums[j] lies within the given range. Which algorithmic approach guarantees an optimal solution for this problem?
easy
A. Use a brute force nested loop to check all pairs and count those with XOR in the range.
B. Use dynamic programming to store counts of XOR values for prefixes and combine them.
C. Sort the array and use two pointers to find pairs with XOR in the range.
D. Build a bitwise trie of the numbers and for each number, query how many previously inserted numbers produce XOR less than or equal to a limit, then combine results for the range.

Solution

  1. Step 1: Understand the problem constraints

    The problem requires counting pairs with XOR in a range efficiently, which brute force (nested loops) is too slow for large inputs.
  2. Step 2: Identify the suitable data structure

    A bitwise trie allows efficient counting of numbers with XOR less than a limit by traversing bits from most significant to least significant.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Bitwise trie approach is known to solve XOR range queries optimally [OK]
Hint: Bitwise trie enables efficient XOR range counting [OK]
Common Mistakes:
  • Thinking sorting + two pointers works for XOR ranges
  • Assuming DP can handle XOR pairs directly
  • Believing brute force is optimal
2. You need to design a data structure that efficiently supports insertion of strings, exact search for strings, and prefix-based search queries. Which of the following data structures guarantees optimal time complexity for these operations regardless of the number of stored strings?
easy
A. Hash Set storing all strings for O(1) average search but no efficient prefix search
B. Trie (Prefix Tree) that stores characters in nodes with links to children nodes
C. Sorting all strings and using binary search for prefix queries
D. Using a balanced binary search tree keyed by entire strings

Solution

  1. Step 1: Understand operation requirements

    Insertion, exact search, and prefix search must be efficient. Hash sets provide O(1) average search but cannot efficiently support prefix queries.
  2. Step 2: Compare data structures

    Tries store characters in nodes allowing O(m) time for insert/search/startsWith, where m is length of word or prefix. Binary search on sorted strings is O(m log n) and BSTs do not support prefix queries efficiently.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Trie supports prefix queries in O(m) time [OK]
Hint: Tries enable prefix queries in O(m) time [OK]
Common Mistakes:
  • Confusing hash sets as supporting prefix queries efficiently
3. You are given a list of words and need to find the shortest prefix for each word that uniquely identifies it among all words. Which approach guarantees an optimal solution in terms of time and space complexity?
easy
A. Build a trie where each node tracks how many words pass through it, then find the prefix where frequency is 1.
B. Sort the words and compare only adjacent words to find the shortest unique prefix.
C. Compare each word's prefixes pairwise with all other words to find uniqueness.
D. Use dynamic programming to store prefix uniqueness states for all words.

Solution

  1. Step 1: Understand problem constraints

    The problem requires finding shortest unique prefixes efficiently for all words, which suggests a data structure that can share prefixes.
  2. Step 2: Evaluate approaches

    Brute force (A) is too slow (O(n^2 * m)). Sorting + adjacent comparison (C) can miss conflicts with non-adjacent words. DP (D) is not a natural fit here. Trie with frequency counts (B) efficiently tracks prefix usage and finds unique prefixes in O(n*m).
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Trie frequency counting matches problem needs [OK]
Hint: Trie frequency counts track prefix uniqueness efficiently [OK]
Common Mistakes:
  • Assuming sorting adjacent words is sufficient for uniqueness
  • Trying brute force despite inefficiency
4. Suppose you want to extend the Trie to support deletion of words. Which of the following approaches correctly handles deletion without breaking prefix searches for other words?
hard
A. Remove the isEnd flag at the last node of the word and delete nodes bottom-up only if they have no children and isEnd is false
B. Delete all nodes corresponding to the word immediately, regardless of children
C. Set isEnd to false at the last node but never delete any nodes
D. Rebuild the entire trie after each deletion to remove unused nodes

Solution

  1. Step 1: Understand deletion impact

    Removing isEnd flag marks word as deleted. Nodes can be deleted only if they are not prefixes of other words.
  2. Step 2: Delete nodes bottom-up conditionally

    Delete nodes only if they have no children and isEnd is false to avoid breaking other words.
  3. Step 3: Avoid unsafe deletions

    Deleting nodes immediately or rebuilding trie is inefficient or breaks other words.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Conditional bottom-up deletion preserves trie correctness [OK]
Hint: Delete nodes only if no children and isEnd is false [OK]
Common Mistakes:
  • Deleting nodes without checking children breaks other words
5. Suppose the problem is modified so that words can be reused multiple times to form longer words (e.g., prefixes can be repeated). Which modification to the trie + BFS approach correctly handles this variant?
hard
A. No change needed; the existing BFS approach already handles reuse of words.
B. Modify BFS to enqueue child nodes even if child.word is None, allowing repeated prefixes.
C. Use DFS with memoization to explore repeated prefixes and avoid cycles.
D. Replace trie with a graph where edges represent possible concatenations and run BFS.

Solution

  1. Step 1: Understand reuse of words

    Allowing reuse means prefixes can be repeated multiple times, potentially causing cycles in traversal.
  2. Step 2: Why DFS with memoization is needed

    DFS with memoization prevents infinite loops by caching results for nodes, correctly handling repeated prefixes and cycles.
  3. Step 3: Why other options fail

    Existing BFS assumes no reuse; enqueuing nodes without word breaks prefix condition; graph BFS without cycle handling risks infinite loops.
  4. Final Answer:

    Option C -> Option C
  5. Quick Check:

    DFS + memoization handles repeated prefixes safely [OK]
Hint: Reuse requires cycle-safe DFS with memoization [OK]
Common Mistakes:
  • Assuming BFS handles reuse without changes
  • Enqueueing invalid nodes breaks prefix rules
  • Ignoring cycles in graph representation
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard