First Non Repeating Character Using Hash in DSA Javascript - Time & Space Complexity
We want to find how fast we can identify the first character in a string that appears only once.
How does the time needed grow as the string gets longer?
Analyze the time complexity of the following code snippet.
function firstNonRepeatingChar(str) {
const charCount = {};
for (const char of str) {
charCount[char] = (charCount[char] || 0) + 1;
}
for (const char of str) {
if (charCount[char] === 1) return char;
}
return null;
}
This code counts how many times each character appears, then finds the first one that appears only once.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Two loops over the string characters.
- How many times: Each loop runs once over all characters, so twice in total.
As the string length grows, the code looks at each character twice, so the work grows roughly twice as much.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 checks |
| 100 | About 200 checks |
| 1000 | About 2000 checks |
Pattern observation: The operations grow linearly with input size, doubling because of two passes.
Time Complexity: O(n)
This means the time needed grows directly in proportion to the string length.
[X] Wrong: "Because there are two loops, the time complexity is O(n²)."
[OK] Correct: The loops run one after another, not nested, so their times add up, not multiply.
Understanding this helps you explain how to efficiently find unique elements using counting, a common skill in coding problems.
"What if we used a nested loop to check each character against all others? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of hash in frequency counting
A hash (object) stores each character as a key and counts how many times it appears in the string.Step 2: Use frequency to find first non repeating character
By checking the hash, we find the first character with count 1, which is the first non repeating character.Final Answer:
To count the frequency of each character in the string -> Option DQuick Check:
Hash counts characters = Frequency count [OK]
- Trying to sort characters instead of counting
- Ignoring character frequency
- Using hash to reverse string
Solution
Step 1: Identify JavaScript object syntax
In JavaScript, curly braces {} create an empty object, which is used as a hash for key-value pairs.Step 2: Confirm correct initialization
Using let hash = {}; correctly initializes an empty object for counting characters.Final Answer:
let hash = {}; -> Option BQuick Check:
Empty object = {} [OK]
- Using [] which creates an array, not an object
- Using () which is invalid syntax
- Using empty string '' which is not an object
function firstNonRepeatingChar(str) {
const hash = {};
for (const ch of str) {
hash[ch] = (hash[ch] || 0) + 1;
}
for (const ch of str) {
if (hash[ch] === 1) return ch;
}
return '_';
}
console.log(firstNonRepeatingChar('swiss'));Solution
Step 1: Count character frequencies in 'swiss'
Characters: s(3), w(1), i(1). Hash = {s:3, w:1, i:1}Step 2: Find first character with count 1 in original order
Order: s, w, i, s, s. First with count 1 is 'w'.Final Answer:
'w' -> Option AQuick Check:
First unique char in 'swiss' = 'w' [OK]
- Returning 's' which repeats
- Returning 'i' which is second unique
- Returning '_' which means no unique char
function firstNonRepeatingChar(str) {
const hash = {};
for (let i = 0; i <= str.length; i++) {
const ch = str[i];
hash[ch] = (hash[ch] || 0) + 1;
}
for (let i = 0; i < str.length; i++) {
if (hash[str[i]] === 1) return str[i];
}
return '_';
}Solution
Step 1: Check loop conditions for index errors
The first loop uses i <= str.length, which accesses str[str.length] (undefined), causing an error.Step 2: Correct loop condition to i < str.length
Changing to i < str.length prevents out-of-bounds access and correctly counts characters.Final Answer:
The first loop uses <= instead of < causing undefined access -> Option CQuick Check:
Loop index must be less than length [OK]
- Using <= causes out-of-range errors
- Ignoring loop boundary conditions
- Misunderstanding hash initialization
'aabbccddeeffg', which modification to the code below will correctly return the first non repeating character?function firstNonRepeatingChar(str) {
const hash = {};
for (const ch of str) {
hash[ch] = (hash[ch] || 0) + 1;
}
for (const ch of str) {
if (hash[ch] === 1) return ch;
}
return '_';
}Options:
A) Change return '_' to return null
B) Add a check to ignore spaces in the string
C) Modify the function to return '_' if no unique character exists
D) Change the hash to store boolean instead of counts
Solution
Step 1: Analyze the string and current function behavior
String 'aabbccddeeffg' has all characters repeated except 'g' which appears once.Step 2: Confirm function returns '_' if no unique char
The function already returns '_' if no unique character is found, which is correct behavior.Step 3: Understand why changing return '_' to return null is better
Changing return '_' to return null clearly indicates no unique character found, which is a better practice than returning a character that might be confused as valid.Final Answer:
Change return '_' to return null -> Option AQuick Check:
Return null when no unique char found is clearer [OK]
- Returning '_' which can be confused as a valid character
- Ignoring spaces when not needed
- Using boolean instead of counts loses frequency info
Ready to prove it?
Pass the test and this pattern moves unknown
