Master advanced hash table techniques through practical implementations and real-world problem solving.
Hash tables are powerful data structures that enable efficient solutions to complex problems. In this guided project, we'll explore advanced applications focusing on character frequency analysis and string manipulation using hash tables.
Hash tables are particularly effective for string operations because they provide:
Initialize a hash map to store character frequencies
This map will associate each character with the number of times it appears in the string.
Iterate through the string to count occurrences
The getOrDefault
method returns the current frequency if the character exists, or 0 if it's not yet in the map.
Search for the first character with frequency 1
We scan the string again in the original order to find the first character with a frequency of 1.
public char findFirstNonRepeating(String str) {
// Edge case: empty string
if (str == null || str.isEmpty()) {
return '_';
}
// Create frequency map
Map frequencyMap = new HashMap<>();
// Count character frequencies
for (char c : str.toCharArray()) {
frequencyMap.put(c, frequencyMap.getOrDefault(c, 0) + 1);
}
// Find first non-repeating character
for (char c : str.toCharArray()) {
if (frequencyMap.get(c) == 1) {
return c;
}
}
// No non-repeating character found
return '_';
}
Let's trace the algorithm with the input string "leetcode":
Character | Frequency | Is First Non-Repeating? |
---|---|---|
'l' | 1 | Yes ✓ |
Check stopped after finding the answer |
If we want to avoid a second pass through the string, we can use a LinkedHashMap, which maintains insertion order:
public char findFirstNonRepeatingOptimized(String str) {
Map frequencyMap = new LinkedHashMap<>();
// Count frequencies
for (char c : str.toCharArray()) {
frequencyMap.put(c, frequencyMap.getOrDefault(c, 0) + 1);
}
// Check the map in insertion order
for (Map.Entry entry : frequencyMap.entrySet()) {
if (entry.getValue() == 1) {
return entry.getKey();
}
}
return '_';
}
Note: This approach is not correct for our specific problem, as it would check characters in order of first appearance rather than original string order.
For large strings, we can optimize by tracking the index of each character's first appearance:
public char findFirstNonRepeatingIndexTracking(String str) {
Map indexMap = new HashMap<>();
Map repeatingMap = new HashMap<>();
// Track first index and whether character repeats
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (!repeatingMap.containsKey(c)) {
// First occurrence
indexMap.put(c, i);
repeatingMap.put(c, false);
} else {
// Repeated occurrence
repeatingMap.put(c, true);
}
}
// Find character with earliest index that doesn't repeat
int minIndex = Integer.MAX_VALUE;
char result = '_';
for (Map.Entry entry : repeatingMap.entrySet()) {
if (!entry.getValue()) {
char c = entry.getKey();
int index = indexMap.get(c);
if (index < minIndex) {
minIndex = index;
result = c;
}
}
}
return result;
}
Implement a method to find the first non-repeating character in a string.
public char findFirstNonRepeating(String str) {
// Your implementation here
// Return the first non-repeating character
// Return '_' if no such character exists
}
Implement a method to find the most frequent character in a string.
public char findMostFrequent(String str) {
// Your implementation here
// Return the most frequent character
}
// Hints:
// 1. Use a HashMap to count character frequencies
// 2. Track the maximum frequency and corresponding character
// 3. Return the character with highest frequency
Implement a method to determine if two strings are anagrams using a hash table.
public boolean areAnagrams(String s1, String s2) {
// Your implementation here
// Return true if strings are anagrams
// Hints:
// 1. Compare string lengths first (quick check)
// 2. Count frequencies of characters in both strings
// 3. Compare the frequency maps
}
Implement a method to check if a string can be rearranged to form a palindrome.
public boolean canFormPalindrome(String str) {
// Your implementation here
// Return true if the string can be rearranged to form a palindrome
// Hint: A string can form a palindrome if at most one character
// appears an odd number of times
}
Find the first unique substring of length k in a string.
public String firstUniqueSubstring(String str, int k) {
// Your implementation here
// Return the first substring of length k that appears only once
// Return an empty string if no such substring exists
// Hint: Use a hash map to track frequencies of substrings
}
Given an array of integers and a target sum, find two numbers that add up to the target.
public int[] twoSum(int[] nums, int target) {
// Your implementation here
// Return indices of the two numbers that add up to target
// Hint: Use a hash map to track values you've seen so far
// If target - current number exists in map, you found the pair
}