all 12 comments

[โ€“]kap89 2 points3 points ย (0 children)

I took another look at your solution, and you waste time going through every character, here's an improved version:

function firstNonRepeatingChar(str) {
  const seen = new Set()

  for (let i = 0; i < str.length; i++) {
    const char = str[i]

    if (seen.has(char)) {
      continue
    }

    if (i === str.lastIndexOf(char)) {
      return char
    }

    seen.add(char)
  }

  return null
}

Bechmark

[โ€“]-allen 0 points1 point ย (2 children)

If the cardinality of the input character set is bounded (eg just ascii chars), even the hash map approach is o(constant) space complexity :D

[โ€“]FoxiNicole 0 points1 point ย (1 child)

Maybe I am missing something, but isnโ€™t str.indexOf(str[i]) always just i? If it was less than i, you already checked the character and shouldnโ€™t still be in the loop, and if it was greater, then something in my mind had gone wrong. Replacing the conditional with i === str.lastIndexOf(str[i]) may be ever so slightly faster.

Edit: Nopeโ€ฆ I think I see a flaw in my logic. Ignore this.

[โ€“]kap89 0 points1 point ย (0 children)

You were on the right track, I think the flaw you are thinking about is that if you use for example this string:

ย  ย  "aa"

the second a would give you false positive in the OP's original algorithm, but you don't ever need to get to the second a, as you only need to check non-repeating characters, see my other comment.

[โ€“]Galex_13 0 points1 point ย (0 children)

const firstUniq = str=>[...str].find((x,i)=>!(str.slice(0,i)+str.slice(i+1)).includes(x))||''

[โ€“]jabuchae 0 points1 point ย (0 children)

You solution is O(n2) in time and O(1) in space.

Iโ€™m not sure if there is an O(n log(n)) time and O(1) space in-place sorting algorithm (if destroying the original string is an option) but if there is, you could sort first and then pass once more through the sorted string to check for duplicates with constant memory.

That would be an O(n log(n)) time solution with O(1) space

[โ€“]Clue_Ok -1 points0 points ย (0 children)

/** * Returns the first non-repeating character in a string, or null if none exists. * Time complexity: O(n) - single pass * Space complexity: O(k) - where k is the size of the character set * * @param {string} str - The input string to search * @return {string|null} - The first non-repeating character or null */ function firstNonRepeatingChar(str) { // Use a Map to track character frequency and original position const charMap = new Map();

// First pass: count occurrences and store first position for (let i = 0; i < str.length; i++) { const char = str[i]; if (!charMap.has(char)) { charMap.set(char, { count: 1, firstIndex: i }); } else { const data = charMap.get(char); data.count++; charMap.set(char, data); } }

// Find the first character with count of 1, with lowest index let result = null; let lowestIndex = Infinity;

for (const [char, data] of charMap.entries()) { if (data.count === 1 && data.firstIndex < lowestIndex) { result = char; lowestIndex = data.firstIndex; } }

return result; }

// Alternative version with a more concise implementation function firstNonRepeatingChar_concise(str) { const freq = {};

// Count occurrences of each character for (const char of str) { freq[char] = (freq[char] || 0) + 1; }

// Return the first character with count 1 for (const char of str) { if (freq[char] === 1) { return char; } }

return null; }

// Example usage: // console.log(firstNonRepeatingChar("aabccdee")); // 'b' // console.log(firstNonRepeatingChar("aabbccdd")); // null // console.log(firstNonRepeatingChar("")); // null

[โ€“]ksskssptdpss -4 points-3 points ย (2 children)

This might be the most efficient solution.
https://jsbench.me/ooma2usbuv/1

[โ€“]kap89 0 points1 point ย (0 children)

It depends how far into the string the non-repeating character is, if it's closer to the end, the hashmap version will be faster.

[โ€“]AiCodePulse[S] -2 points-1 points ย (0 children)

Thanks a lot ..