First Non-Repeating Character

August 19, 2011

This question appears on several lists of interview questions:

Write a function that takes an input string and returns the first character from the string that is not repeated later in the string. For instance, the two letters “d” and “f” in the input string “aabcbcdeef” are non-repeating, and the function should return “d” since “f” appears later in the string. The function should return some indication if there are no non-repeating characters in the string.

Your task is to write the indicated function. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Rather than make two passes through the whole string, I make one pass through
the string and then one pass through all the unique characters (by calling min on
the “position” dictionary). If there are few unique characters in the string, this may
speed up the work significantly.

@Mike: super slick answer, but I think you might run into trouble with strings
in which all characters repeat—e.g. ‘aabbcc’—where it “should return some
indication if there are no non-repeating characters in the string,” or with
empty strings (perhaps a useless edgecase).

@Graham. Just after I posted my first solution, I realized it didn’t work if there were no unique characters. The idea for the Ordered Counter came straight from the Python 3 documentation for OrderedDict, so I can’t take credit for that.

I first tried a solution similar to yours. However, when a repeated letter is seen it is popped from the position dictionary–effectively “forgetting” that the letter had been seen. If a letter appears a third time, it will seem to be unique. Ex: fst_non_rep(‘ababac’) returns ‘a’ instead of ‘c’.

If a character is not on either the repeat or nonrepeat lists, add it to the nonrepeat. If it’s on the nonrepeat, remove it and add it to the repeat list, otherwise we’ve already seen it and it’s on the repeat list already. Return either the first item on the nonrepeat list if it’s not empty or the empty string if it is. I think this should work in all cases. We’re letting the ruby array class do all the hard work here.

Basically Gambit-C with extensions…
Recursively construct an occurrences table, and when returning, check if head of intermediate list as only one occurrence (guaranteeing the “first” unique element will be returned). Returns “#f” if no unique char.
A bit verbose, but pretty direct.
Basically, O(n).

Hey!
Just found this site through sixrevisions.com and thought I might have a try on one of the puzzles! So I’m a student in java-programming among other stuff, so that’s the language I used for my solution. Here goes:

Here is my Racket solution. I’ve used two tables to map each character to the number of occurrences (and viceversa); this way, it is possible to solve this with no conditionals (with the exception of the implicit one in the “for” construct) and traversing the string only once.

A different approach is to split the parsed characters into two sets, RC – containing repeating characters and NRC – containing not repeating characters.
First look at RC, if the character is there, go next. Otherwise, if the character is in NRC, move it to RC and go next. Otherwise put the character in NRC.. and go next.
NRC can be ordered by combining an hashset with a double linked list, so the first not repeating character is the first one left in NRC.
The resulting function parses the string only once at the cost of a bit more complex data structure.

These days there are over a million possible characters and over a hundred thousand defined characters (in Unicode). It wasn’t clear to me what is supposed
to happen for an empty string or for say ‘ee’. (Arguably, when you look at the
*last* $e it is not followed by another copy, so the answer then is $e.)