336. Palindrome Pairs
Problem Description
You are given an array of unique strings called words
. Your task is to find all pairs of indices (i, j)
where concatenating words[i]
and words[j]
forms a palindrome.
A valid palindrome pair must satisfy:
- Both indices
i
andj
are within the array bounds (0 to length-1) - The indices must be different (
i != j
) - The concatenation
words[i] + words[j]
reads the same forwards and backwards
For example, if words = ["abc", "cba"]
, then the pair (0, 1)
would be valid because "abc" + "cba" = "abccba"
is a palindrome.
The algorithm examines each word and splits it at every possible position. For each split:
- It checks if the reverse of the left part exists in the word list and if the right part is already a palindrome
- It checks if the reverse of the right part exists in the word list and if the left part is already a palindrome
The solution uses a hash map to store word-to-index mappings for O(1) lookups. For each word, it iterates through all possible split positions (0 to word length). At each split position j
:
a
= firstj
characters,b
= remaining charactersra
= reverse ofa
,rb
= reverse ofb
- If
ra
exists in the word list andb
is a palindrome, then[current_index, index_of_ra]
forms a valid pair - If
rb
exists in the word list anda
is a palindrome, then[index_of_rb, current_index]
forms a valid pair
The condition j > 0
in the second check prevents duplicate pairs when dealing with empty string splits.
The time complexity requirement is O(sum of all word lengths), which this solution achieves by processing each character of each word a constant number of times.
Intuition
The key insight is that if two words concatenate to form a palindrome, there must be a special relationship between their characters. Let's think about what happens when word1 + word2
forms a palindrome.
Consider the concatenated string as having a "pivot point" somewhere. For the result to be a palindrome, the characters before the pivot must mirror the characters after it. This pivot could be:
- Inside
word1
- Inside
word2
- Exactly at the boundary between the two words
Let's explore case 1 where the pivot is inside word1
. If we split word1
into two parts [prefix][suffix]
, then for [prefix][suffix][word2]
to be a palindrome:
- The
prefix
must be a palindrome by itself (since it needs to mirror itself around the pivot) - The
suffix + word2
must read the same asword2 + suffix
reversed - This means
word2
must equal the reverse ofsuffix
Similarly, if the pivot is in word2
, we split it as [prefix][suffix]
and for [word1][prefix][suffix]
to be a palindrome:
- The
suffix
must be a palindrome by itself word1
must equal the reverse ofprefix
This naturally leads us to the approach: for each word, try all possible split positions. At each split:
- Check if one part is a palindrome
- Check if the reverse of the other part exists in our word list
- If both conditions are met, we've found a valid palindrome pair
The beauty of this approach is that it systematically covers all possible pivot positions. By checking both directions (word as first element and word as second element), we ensure we find all valid pairs.
Using a hash map to store word-to-index mappings allows us to quickly check if a reversed substring exists in our word list, making the algorithm efficient enough to meet the time complexity requirement.
Solution Approach
The implementation uses a hash map and string manipulation to efficiently find all palindrome pairs:
1. Build Hash Map for O(1) Lookups
d = {w: i for i, w in enumerate(words)}
Create a dictionary mapping each word to its index. This allows constant-time lookups when checking if a reversed substring exists in the word list.
2. Iterate Through Each Word
for i, w in enumerate(words):
Process each word in the array along with its index.
3. Try All Possible Split Positions
for j in range(len(w) + 1):
a, b = w[:j], w[j:]
For each word, split it at every position from 0 to its length. This creates two parts:
a
: prefix (firstj
characters)b
: suffix (remaining characters)
The +1
in the range ensures we also consider the case where one part is empty.
4. Calculate Reverses
ra, rb = a[::-1], b[::-1]
Compute the reverse of both parts for checking palindrome conditions and dictionary lookups.
5. Check First Configuration: Current Word as First Element
if ra in d and d[ra] != i and b == rb: ans.append([i, d[ra]])
This checks if words[i] + words[d[ra]]
forms a palindrome:
ra in d
: The reverse of prefixa
exists in our word listd[ra] != i
: Ensure we're not pairing a word with itselfb == rb
: The suffixb
is a palindrome
If all conditions are met, [prefix_a][suffix_b] + [reverse_of_a]
forms a palindrome.
6. Check Second Configuration: Current Word as Second Element
if j and rb in d and d[rb] != i and a == ra: ans.append([d[rb], i])
This checks if words[d[rb]] + words[i]
forms a palindrome:
j > 0
: Avoid duplicates whenj=0
(empty prefix case already handled in first check)rb in d
: The reverse of suffixb
exists in our word listd[rb] != i
: Ensure different indicesa == ra
: The prefixa
is a palindrome
If all conditions are met, [reverse_of_b] + [prefix_a][suffix_b]
forms a palindrome.
Time Complexity Analysis:
- For each word of length
m
, we performm+1
splits - Each split involves creating substrings and checking palindromes: O(m) operations
- Total: O(n Γ m Γ m) where n is the number of words and m is average word length
- Since we process each character a constant number of times across all operations, this meets the O(sum of word lengths) requirement when properly analyzed
The algorithm elegantly handles all cases including empty strings and ensures no duplicate pairs are added to the result.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the algorithm with words = ["bat", "tab", "cat"]
.
Step 1: Build Hash Map
d = {"bat": 0, "tab": 1, "cat": 2}
Step 2: Process word "bat" (index 0)
Split at position 0:
a = ""
,b = "bat"
ra = ""
,rb = "tab"
- Check 1: Is
ra
("") in dictionary? No, skip. - Check 2: Skip (j = 0)
Split at position 1:
a = "b"
,b = "at"
ra = "b"
,rb = "ta"
- Check 1: Is
ra
("b") in dictionary? No, skip. - Check 2: Is
rb
("ta") in dictionary? No, skip.
Split at position 2:
a = "ba"
,b = "t"
ra = "ab"
,rb = "t"
- Check 1: Is
ra
("ab") in dictionary? No, skip. - Check 2: Is
rb
("t") in dictionary? No, skip.
Split at position 3:
a = "bat"
,b = ""
ra = "tab"
,rb = ""
- Check 1: Is
ra
("tab") in dictionary? Yes! Index 1.- Is
d["tab"] != 0
? Yes (1 β 0). - Is
b == rb
("" == "")? Yes, palindrome! - Found pair: [0, 1] β "bat" + "tab" = "battab" β
- Is
- Check 2: Is
rb
("") in dictionary? No, skip.
Step 3: Process word "tab" (index 1)
Split at position 0:
a = ""
,b = "tab"
ra = ""
,rb = "bat"
- Check 1: Is
ra
("") in dictionary? No, skip. - Check 2: Skip (j = 0)
Split at position 1:
a = "t"
,b = "ab"
ra = "t"
,rb = "ba"
- Check 1: Is
ra
("t") in dictionary? No, skip. - Check 2: Is
rb
("ba") in dictionary? No, skip.
Split at position 2:
a = "ta"
,b = "b"
ra = "at"
,rb = "b"
- Check 1: Is
ra
("at") in dictionary? No, skip. - Check 2: Is
rb
("b") in dictionary? No, skip.
Split at position 3:
a = "tab"
,b = ""
ra = "bat"
,rb = ""
- Check 1: Is
ra
("bat") in dictionary? Yes! Index 0.- Is
d["bat"] != 1
? Yes (0 β 1). - Is
b == rb
("" == "")? Yes, palindrome! - Found pair: [1, 0] β "tab" + "bat" = "tabbat" β
- Is
- Check 2: Is
rb
("") in dictionary? No, skip.
Step 4: Process word "cat" (index 2)
After checking all splits for "cat", no valid pairs are found because:
- "tac" (reverse of "cat") is not in the dictionary
- No partial reverses match with palindromic remainders
Final Result: [[0, 1], [1, 0]]
Both pairs form palindromes:
- "bat" + "tab" = "battab" (palindrome β)
- "tab" + "bat" = "tabbat" (palindrome β)
Solution Implementation
1class Solution:
2 def palindromePairs(self, words: List[str]) -> List[List[int]]:
3 # Create a dictionary mapping each word to its index for O(1) lookup
4 word_to_index = {word: index for index, word in enumerate(words)}
5 result = []
6
7 # Check each word for potential palindrome pairs
8 for current_index, current_word in enumerate(words):
9 # Try splitting the current word at every possible position
10 for split_pos in range(len(current_word) + 1):
11 # Split current word into prefix and suffix
12 prefix = current_word[:split_pos]
13 suffix = current_word[split_pos:]
14
15 # Get reversed versions of prefix and suffix
16 reversed_prefix = prefix[::-1]
17 reversed_suffix = suffix[::-1]
18
19 # Case 1: If reversed_prefix exists in words and suffix is palindrome
20 # Then current_word + words[reversed_prefix_index] forms a palindrome
21 if reversed_prefix in word_to_index and word_to_index[reversed_prefix] != current_index and suffix == reversed_suffix:
22 result.append([current_index, word_to_index[reversed_prefix]])
23
24 # Case 2: If reversed_suffix exists in words and prefix is palindrome
25 # Then words[reversed_suffix_index] + current_word forms a palindrome
26 # Note: split_pos > 0 prevents duplicate when both prefix and suffix are empty
27 if split_pos > 0 and reversed_suffix in word_to_index and word_to_index[reversed_suffix] != current_index and prefix == reversed_prefix:
28 result.append([word_to_index[reversed_suffix], current_index])
29
30 return result
31
1class Solution {
2 // Constants for rolling hash computation
3 private static final int HASH_BASE = 131; // Prime number base for polynomial rolling hash
4 private static final long[] POWER_BASE = new long[310]; // Precomputed powers of base
5 private static final int HASH_MOD = (int) 1e9 + 7; // Large prime modulus to prevent overflow
6
7 // Static initialization block to precompute powers of base
8 static {
9 POWER_BASE[0] = 1;
10 for (int i = 1; i < POWER_BASE.length; ++i) {
11 POWER_BASE[i] = (POWER_BASE[i - 1] * HASH_BASE) % HASH_MOD;
12 }
13 }
14
15 public List<List<Integer>> palindromePairs(String[] words) {
16 int wordCount = words.length;
17
18 // Arrays to store forward and reverse hash values for each word
19 long[] forwardHash = new long[wordCount];
20 long[] reverseHash = new long[wordCount];
21
22 // Calculate hash values for each word
23 for (int i = 0; i < wordCount; ++i) {
24 String currentWord = words[i];
25 int wordLength = currentWord.length();
26
27 // Build forward hash (left to right) and reverse hash (right to left)
28 for (int j = 0; j < wordLength; ++j) {
29 // Convert character to 1-based value (a=1, b=2, ..., z=26)
30 int forwardChar = currentWord.charAt(j) - 'a' + 1;
31 int reverseChar = currentWord.charAt(wordLength - j - 1) - 'a' + 1;
32
33 // Update hash values using polynomial rolling hash formula
34 forwardHash[i] = (forwardHash[i] * HASH_BASE) % HASH_MOD + forwardChar;
35 reverseHash[i] = (reverseHash[i] * HASH_BASE) % HASH_MOD + reverseChar;
36 }
37 }
38
39 List<List<Integer>> result = new ArrayList<>();
40
41 // Check all pairs of words
42 for (int i = 0; i < wordCount; ++i) {
43 for (int j = i + 1; j < wordCount; ++j) {
44 // Check if words[i] + words[j] forms a palindrome
45 if (isPalindromeConcatenation(i, j, words[j].length(), words[i].length(),
46 forwardHash, reverseHash)) {
47 result.add(Arrays.asList(i, j));
48 }
49
50 // Check if words[j] + words[i] forms a palindrome
51 if (isPalindromeConcatenation(j, i, words[i].length(), words[j].length(),
52 forwardHash, reverseHash)) {
53 result.add(Arrays.asList(j, i));
54 }
55 }
56 }
57
58 return result;
59 }
60
61 /**
62 * Checks if concatenation of words at index firstIdx and secondIdx forms a palindrome
63 *
64 * @param firstIdx Index of the first word in concatenation
65 * @param secondIdx Index of the second word in concatenation
66 * @param secondWordLen Length of the second word
67 * @param firstWordLen Length of the first word
68 * @param forwardHash Array containing forward hash values
69 * @param reverseHash Array containing reverse hash values
70 * @return true if concatenation forms a palindrome, false otherwise
71 */
72 private boolean isPalindromeConcatenation(int firstIdx, int secondIdx, int secondWordLen,
73 int firstWordLen, long[] forwardHash, long[] reverseHash) {
74 // Calculate hash of concatenated string (first word + second word)
75 long concatenatedForwardHash = ((forwardHash[firstIdx] * POWER_BASE[secondWordLen]) % HASH_MOD
76 + forwardHash[secondIdx]) % HASH_MOD;
77
78 // Calculate hash of reverse of concatenated string
79 // Reverse of (A + B) = reverse(B) + reverse(A)
80 long concatenatedReverseHash = ((reverseHash[secondIdx] * POWER_BASE[firstWordLen]) % HASH_MOD
81 + reverseHash[firstIdx]) % HASH_MOD;
82
83 // If forward and reverse hashes match, the concatenation is a palindrome
84 return concatenatedForwardHash == concatenatedReverseHash;
85 }
86}
87
1class Solution {
2private:
3 // Constants for rolling hash computation
4 static constexpr int HASH_BASE = 131; // Prime number base for polynomial rolling hash
5 static constexpr int HASH_MOD = 1000000007; // Large prime modulus to prevent overflow
6 static constexpr int MAX_LENGTH = 310;
7
8 // Precomputed powers of base
9 vector<long long> powerBase;
10
11 /**
12 * Checks if concatenation of words at index firstIdx and secondIdx forms a palindrome
13 *
14 * @param firstIdx Index of the first word in concatenation
15 * @param secondIdx Index of the second word in concatenation
16 * @param secondWordLen Length of the second word
17 * @param firstWordLen Length of the first word
18 * @param forwardHash Vector containing forward hash values
19 * @param reverseHash Vector containing reverse hash values
20 * @return true if concatenation forms a palindrome, false otherwise
21 */
22 bool isPalindromeConcatenation(int firstIdx, int secondIdx, int secondWordLen,
23 int firstWordLen, const vector<long long>& forwardHash,
24 const vector<long long>& reverseHash) {
25 // Calculate hash of concatenated string (first word + second word)
26 long long concatenatedForwardHash = ((forwardHash[firstIdx] * powerBase[secondWordLen]) % HASH_MOD
27 + forwardHash[secondIdx]) % HASH_MOD;
28
29 // Calculate hash of reverse of concatenated string
30 // Reverse of (A + B) = reverse(B) + reverse(A)
31 long long concatenatedReverseHash = ((reverseHash[secondIdx] * powerBase[firstWordLen]) % HASH_MOD
32 + reverseHash[firstIdx]) % HASH_MOD;
33
34 // If forward and reverse hashes match, the concatenation is a palindrome
35 return concatenatedForwardHash == concatenatedReverseHash;
36 }
37
38 /**
39 * Initialize power base array with precomputed powers
40 */
41 void initializePowerBase() {
42 powerBase.resize(MAX_LENGTH);
43 powerBase[0] = 1;
44 for (int i = 1; i < MAX_LENGTH; ++i) {
45 powerBase[i] = (powerBase[i - 1] * HASH_BASE) % HASH_MOD;
46 }
47 }
48
49public:
50 vector<vector<int>> palindromePairs(vector<string>& words) {
51 // Initialize power base array
52 initializePowerBase();
53
54 int wordCount = words.size();
55
56 // Vectors to store forward and reverse hash values for each word
57 vector<long long> forwardHash(wordCount, 0);
58 vector<long long> reverseHash(wordCount, 0);
59
60 // Calculate hash values for each word
61 for (int i = 0; i < wordCount; ++i) {
62 const string& currentWord = words[i];
63 int wordLength = currentWord.length();
64
65 // Build forward hash (left to right) and reverse hash (right to left)
66 for (int j = 0; j < wordLength; ++j) {
67 // Convert character to 1-based value (a=1, b=2, ..., z=26)
68 int forwardChar = currentWord[j] - 'a' + 1;
69 int reverseChar = currentWord[wordLength - j - 1] - 'a' + 1;
70
71 // Update hash values using polynomial rolling hash formula
72 forwardHash[i] = (forwardHash[i] * HASH_BASE) % HASH_MOD + forwardChar;
73 reverseHash[i] = (reverseHash[i] * HASH_BASE) % HASH_MOD + reverseChar;
74 }
75 }
76
77 vector<vector<int>> result;
78
79 // Check all pairs of words
80 for (int i = 0; i < wordCount; ++i) {
81 for (int j = i + 1; j < wordCount; ++j) {
82 // Check if words[i] + words[j] forms a palindrome
83 if (isPalindromeConcatenation(i, j, words[j].length(), words[i].length(),
84 forwardHash, reverseHash)) {
85 result.push_back({i, j});
86 }
87
88 // Check if words[j] + words[i] forms a palindrome
89 if (isPalindromeConcatenation(j, i, words[i].length(), words[j].length(),
90 forwardHash, reverseHash)) {
91 result.push_back({j, i});
92 }
93 }
94 }
95
96 return result;
97 }
98};
99
1// Constants for rolling hash computation
2const HASH_BASE = 131; // Prime number base for polynomial rolling hash
3const POWER_BASE: number[] = new Array(310); // Precomputed powers of base
4const HASH_MOD = 1e9 + 7; // Large prime modulus to prevent overflow
5
6// Initialize precomputed powers of base
7POWER_BASE[0] = 1;
8for (let i = 1; i < POWER_BASE.length; i++) {
9 POWER_BASE[i] = (POWER_BASE[i - 1] * HASH_BASE) % HASH_MOD;
10}
11
12/**
13 * Finds all pairs of words that form palindromes when concatenated
14 * @param words - Array of words to check for palindrome pairs
15 * @returns List of index pairs [i, j] where words[i] + words[j] forms a palindrome
16 */
17function palindromePairs(words: string[]): number[][] {
18 const wordCount = words.length;
19
20 // Arrays to store forward and reverse hash values for each word
21 const forwardHash: number[] = new Array(wordCount).fill(0);
22 const reverseHash: number[] = new Array(wordCount).fill(0);
23
24 // Calculate hash values for each word
25 for (let i = 0; i < wordCount; i++) {
26 const currentWord = words[i];
27 const wordLength = currentWord.length;
28
29 // Build forward hash (left to right) and reverse hash (right to left)
30 for (let j = 0; j < wordLength; j++) {
31 // Convert character to 1-based value (a=1, b=2, ..., z=26)
32 const forwardChar = currentWord.charCodeAt(j) - 'a'.charCodeAt(0) + 1;
33 const reverseChar = currentWord.charCodeAt(wordLength - j - 1) - 'a'.charCodeAt(0) + 1;
34
35 // Update hash values using polynomial rolling hash formula
36 forwardHash[i] = ((forwardHash[i] * HASH_BASE) % HASH_MOD + forwardChar) % HASH_MOD;
37 reverseHash[i] = ((reverseHash[i] * HASH_BASE) % HASH_MOD + reverseChar) % HASH_MOD;
38 }
39 }
40
41 const result: number[][] = [];
42
43 // Check all pairs of words
44 for (let i = 0; i < wordCount; i++) {
45 for (let j = i + 1; j < wordCount; j++) {
46 // Check if words[i] + words[j] forms a palindrome
47 if (isPalindromeConcatenation(
48 i,
49 j,
50 words[j].length,
51 words[i].length,
52 forwardHash,
53 reverseHash
54 )) {
55 result.push([i, j]);
56 }
57
58 // Check if words[j] + words[i] forms a palindrome
59 if (isPalindromeConcatenation(
60 j,
61 i,
62 words[i].length,
63 words[j].length,
64 forwardHash,
65 reverseHash
66 )) {
67 result.push([j, i]);
68 }
69 }
70 }
71
72 return result;
73}
74
75/**
76 * Checks if concatenation of words at specified indices forms a palindrome
77 *
78 * @param firstIdx - Index of the first word in concatenation
79 * @param secondIdx - Index of the second word in concatenation
80 * @param secondWordLen - Length of the second word
81 * @param firstWordLen - Length of the first word
82 * @param forwardHash - Array containing forward hash values
83 * @param reverseHash - Array containing reverse hash values
84 * @returns true if concatenation forms a palindrome, false otherwise
85 */
86function isPalindromeConcatenation(
87 firstIdx: number,
88 secondIdx: number,
89 secondWordLen: number,
90 firstWordLen: number,
91 forwardHash: number[],
92 reverseHash: number[]
93): boolean {
94 // Calculate hash of concatenated string (first word + second word)
95 const concatenatedForwardHash = (
96 (forwardHash[firstIdx] * POWER_BASE[secondWordLen]) % HASH_MOD +
97 forwardHash[secondIdx]
98 ) % HASH_MOD;
99
100 // Calculate hash of reverse of concatenated string
101 // Reverse of (A + B) = reverse(B) + reverse(A)
102 const concatenatedReverseHash = (
103 (reverseHash[secondIdx] * POWER_BASE[firstWordLen]) % HASH_MOD +
104 reverseHash[firstIdx]
105 ) % HASH_MOD;
106
107 // If forward and reverse hashes match, the concatenation is a palindrome
108 return concatenatedForwardHash === concatenatedReverseHash;
109}
110
Time and Space Complexity
Time Complexity: O(n * k^2)
where n
is the number of words and k
is the average length of each word.
- Building the dictionary takes
O(n * k)
time (iterating throughn
words, each hash operation takesO(k)
) - The outer loop iterates through
n
words - For each word, the inner loop runs
k + 1
times (wherek
is the length of current word) - Inside the inner loop:
- Slicing operations
w[:j]
andw[j:]
takeO(k)
time - Reversing strings
a[::-1]
andb[::-1]
takeO(k)
time - Checking palindrome conditions
b == rb
anda == ra
takeO(k)
time - Dictionary lookups take
O(k)
time (comparing string keys)
- Slicing operations
- Total:
O(n * k * k)
=O(n * k^2)
Space Complexity: O(n * k)
- The dictionary
d
storesn
words as keys, requiringO(n * k)
space - The
ans
list can store at mostO(n^2)
pairs, but each pair only contains two integers, so it'sO(n^2)
for the answer list - Temporary variables
a
,b
,ra
,rb
each take up toO(k)
space - Since typically
k << n
in this problem context, and the dictionary dominates the space usage, the overall space complexity isO(n * k)
when considering string storage
Common Pitfalls
1. Duplicate Pairs from Empty String Splits
The most critical pitfall is generating duplicate pairs when handling empty string splits. When j=0
, the prefix is empty and when j=len(word)
, the suffix is empty. Without proper handling, both cases can identify the same palindrome pair.
Problem Example:
words = ["abc", "cba"] # When processing "abc" at j=0: # prefix="" (palindrome), suffix="abc" # If reverse of suffix ("cba") exists β pair [1, 0] # When processing "cba" at j=3: # prefix="cba", suffix="" (palindrome) # If reverse of prefix ("abc") exists β pair [1, 0] again!
Solution:
The condition if split_pos > 0
in the second check prevents this duplication by ensuring empty prefix cases are only handled in the first check.
2. Self-Pairing Prevention
Another common mistake is forgetting to check d[ra] != i
or d[rb] != i
, which would allow a word to pair with itself.
Problem Example:
words = ["aba"] # "aba" is itself a palindrome # Without the self-check, might incorrectly add [0, 0]
Solution:
Always include the condition word_to_index[reversed_part] != current_index
to prevent self-pairing.
3. Incorrect Palindrome Validation
A subtle error occurs when checking if concatenations form palindromes. The algorithm must verify that the non-matching part (the part not being looked up) is itself a palindrome.
Problem Example:
words = ["ab", "ba", "abc"] # For "abc" split as "ab" + "c": # reverse("ab") = "ba" exists in words # But "c" is not a palindrome # "abc" + "ba" = "abcba" is NOT a palindrome
Solution:
Always verify suffix == reversed_suffix
or prefix == reversed_prefix
to ensure the remaining part is palindromic.
4. Edge Case: Empty Strings in Input
If the input contains empty strings, special care is needed as any palindrome concatenated with an empty string remains a palindrome.
Problem Example:
words = ["", "aba", "xyz"] # "" + "aba" = "aba" (palindrome) # "aba" + "" = "aba" (palindrome)
Solution: The algorithm naturally handles this case, but be aware that empty strings will match with all palindromic words in the list, potentially creating many valid pairs.
5. Performance Degradation with Hash Collisions
While using a hash map provides O(1) average lookup time, worst-case scenarios with many hash collisions could degrade performance.
Solution: Use Python's built-in dictionary which handles hash collisions efficiently. For extremely large datasets, consider additional optimization strategies like prefix trees (tries) for substring matching.
What is the best way of checking if an element exists in an unsorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Trie Introduction Imagine you have a magic dictionary where as soon as you start spelling a word it immediately tells you how many words that start with those letters How cool would that be This is exactly the kind of magic a data structure called trie performs What's a Trie
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!