April 30, 2013 9:00 AM
We have today another exercise from our never-ending supply of interview questions:
Given a string, find the first character that appears only once in the string. For instance, given the string “aabbcddd”, the first character that appears only once is the “c” found at the 4th character in the string, counting from 0. Be sure that your program properly handles the case that all characters appear more than once.
Your task is to write a program that finds the first unrepeated character in a string, and its index in the string. 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.
Posted by programmingpraxis
Categories: Exercises
Tags:
Mobile Site | Full Site
Get a free blog at WordPress.com Theme: WordPress Mobile Edition by Alex King.
#|
Given a string, find the first character that appears only once
in the string. For instance, given the string “aabbcddd”, the
first character that appears only once is the “c” found at the
4th character in the string, counting from 0. Be sure that your
program properly handles the case that all characters appear more
than once.
|#
(defun first-singleton (sequence &key (test (function eql)))
(let ((histogram (make-hash-table :test test :size (length sequence))))
(map nil (let ((index -1))
(lambda (element)
(let ((entry (gethash element histogram)))
(if entry
(incf (cdr entry))
(setf (gethash element histogram) (cons (incf index) 1))))))
sequence)
(let ((min-element nil)
(min-index nil))
(maphash (lambda (element entry)
(destructuring-bind (first-index . occurences) entry
(when (and (= 1 occurences)
(or (null min-index)
(< first-index min-index)))
(setf min-index first-index
min-element element))))
histogram)
(values min-element min-index))))
;; (first-singleton “aabbcddd”)
;; #\c
;; 2
;;
;; (first-singleton “aabbcccddd”)
;; NIL
;; NIL
;;
;; (first-singleton ‘(t nil t t))
;; NIL
;; 1
;;
;; (first-singleton ‘(t nil nil t t))
;; NIL
;; NIL
By Pascal Bourguignon on April 30, 2013 at 12:06 PM
The solution you’re proposing doesn’t work: (f “∀x∈N, x+1≥x ∧ x+1∈N”) may return 2, or may signal an error!
By Pascal Bourguignon on April 30, 2013 at 1:07 PM
[…] today’s Programming Praxis exercise, our goal is to find the find the first unrepeated character in a […]
By Programming Praxis – First Unrepeated Character In A String | Bonsai Code on April 30, 2013 at 1:07 PM
My Haskell solution (see http://bonsaicode.wordpress.com/2013/04/30/programming-praxis-first-unrepeated-character-in-a-string/ for a version with comments):
import Data.Maybe import Data.List unrepeated :: String -> Maybe (Integer, Char) unrepeated = listToMaybe . snd . foldr f ([], []) . zip [0..] where f (i,c) (ds,us) = if elem c ds then (ds, us) else maybe (ds, (i,c):us) (\(fi,fc) -> (fc:ds, delete (fi,fc) us)) $ find ((== c) . snd) usBy Remco Niemeijer on April 30, 2013 at 1:07 PM
Python solution. The complexity is not optimal, but it is short and easy to understand.
def first_unrepeated(s): for i, c in enumerate(s): if s.count(c) == 1: return i if __name__ == "__main__": examples = [ "aaab", "aaabbbcddd", "aaaebbbcddd", "aabbcc"] examples += [ "aabbcddd", "aabbcccddd" ] examples += [ [True, False, True, True], [True, False, False, True, True] ] for s in examples: print first_unrepeated(s)By Jan Van lent on April 30, 2013 at 1:51 PM
Using the 8-bit value of the character as an index into a lookup table breaks when you want to deal with Unicode text.
An O(n^2) approach which requires only O(1) additional memory would be to do something like this:
for (i = 0 to len – 2) {
duplicate = false;
for (j = i + 1 to len – 1) {
if (s[i] == s[j]) { duplicate = true; break; }
}
if (!duplicate) { return i; }
}
return -1;
An O(n log n) approach which requires O(n) additional memory would be to:
1. build an array of { character, index } elements
2. sort it by .character
3. walk the sorted array looking at all unique characters
4. return the lowest-valued .index
By Maurits on April 30, 2013 at 2:04 PM
Python version using Counter and OrderedDict from the standard library to build an OrderedCounter.
By Mike on April 30, 2013 at 4:52 PM
#include
#include
#define NO_OF_CHARS 256
/* Returns an array of size 256 containg count
of characters in the passed char array */
int *getCharCountArray(char *str)
{
int *count = (int *)calloc(sizeof(int), NO_OF_CHARS);
int i;
for (i = 0; *(str+i); i++)
count[*(str+i)]++;
return count;
}
/* The function returns index of first non-repeating
character in a string. If all characters are repeating
then reurns -1 */
int firstNonRepeating(char *str)
{
int *count = getCharCountArray(str);
int index = -1, i;
for (i = 0; *(str+i); i++)
{
if(count[*(str+i)] == 1)
{
index = i;
break;
}
}
return index;
}
/* Driver program to test above function */
int main()
{
char str[] = “geeksforgeeks”;
int index = firstNonRepeating(str);
if(index == -1)
printf(“Either all characters are repeating or string is empty”);
else
printf(“First non-repeating character is %c”, str[index]);
getchar();
return 0;
}
By Shail on May 1, 2013 at 4:15 PM
def unrepeatedcharacter(string):
for i in range(0, len(string)):
if string[i] not in string[:i] + string[i + 1:]:
return string[i]
return None
By margaruga on May 1, 2013 at 6:08 PM
def unrepeatedcharacter(string): for i in range(0, len(string)): if string[i] not in string[:i] + string[i + 1:]: return string[i] return NoneBy margaruga on May 1, 2013 at 6:11 PM
There’s a slight variation on the algorithm you gave which I think is slightly simpler and could possibly be faster, at least if the first unrepeated element occurs relatively early in the string.
Start by creating an array that just keeps a count of how many times each character occurs. Then let the second loop go through the string again and look up the occurs count for each character. The first one which occurs once is the answer. In order to return the index, the loop just have to keep track of the current index as it traverses the string.
Haskell code:
import Data.Array unrepeat :: String -> Maybe (Int,Char) unrepeat str = loop 0 str $ accumArray (+) 0 ('a','z') $ zip str (repeat 1) where loop i [] arr = Nothing loop i (a:as) arr | arr!a == 1 = Just (i,a) | otherwise = loop (i+1) as arrBy Josef Svenningsson on May 1, 2013 at 8:25 PM
Not the very prettiest solution, but I’d say near optimal in time.
def first_unrepeated(string): good, bad = {}, [] for i, char in enumerate(string): if char in bad: continue if char in good: del good[s] bad.append(s) continue good[s] = i return good and min(good.items(), key=lambda x: x[1]) or NoneBy Josh on May 2, 2013 at 3:16 AM
Obviously it should be:
def first_unrepeated(string): good, bad = {}, [] for i, char in enumerate(string): if char in bad: continue if char in good: del good[char] bad.append(char) continue good[char] = i return good and min(good.items(), key=lambda x: x[1]) or NoneBy Josh on May 2, 2013 at 3:19 AM
well, thanks for your suggestion..
i am just a beginner to C so acc to me my logic is good
still will study yours script
:)
By Shail on May 2, 2013 at 3:20 AM
Most high-level languages have string searching and splitting operations, but using these kind of defeats the purpose of the exercise.
The essential method, find_first_singleton is pasted below. The complete program, with tests, is available at codepad.org
# String.each_char_with_index {|c| code block with #c } class String def each_char_with_index x = 0 while x < self.length do char = self[x,1] yield [char, x] x += 1 end end # String.find_first_singleton(char) => [char, index] or nil def find_first_singleton letters = {} # hash of letters & occurences self.each_char_with_index do |letter, x| letters[letter] ||= 0 letters[letter] += 1 end # all letters counted; find the first with count == 1 self.each_char_with_index do |letter, x| return [letter, x] if letters[letter] == 1 end nil end end # String enhancementHere is the invocation of the method find_first_singleton:
str = ARGV.shift # get the argument puts "Input: #{str}" puts str.find_first_singleton.prettyBy Alan S. on May 2, 2013 at 4:38 AM
Another solution, using the very high-level language, J (see J Software).
First, let’s see the solution, then show how it works.
ffs =: monad define
n =. 1 i.~ +/e. y
if. (n>:#y) do. (0$0) else. ((n{y);n) end.
)
Examples of usage:
ffs ‘foo’
+-+-+
|f|0|
+-+-+
ffs ‘oof’
+-+-+
|f|2|
+-+-+
ffs ‘foobar’
+-+-+
|f|0|
+-+-+
ffs ‘oofbar’
+-+-+
|f|2|
+-+-+
ffs ‘oofbarf’
+-+-+
|b|3|
+-+-+
ffs ‘boofbarf’
+-+-+
|a|5|
+-+-+
ffs ‘aabbcc’
Notice that the last invocation produced no value.
Okay. How did that work?
The expression “e. y” means “member in” the monadic function argument “y”. In the examples above, the arguments given to the function are represented as “y” within the function definition.
So, the expression below produces a boolean array indicating where each letter of the argument occurs
e. ‘foobar’
1 0 0 0 0 0
0 1 1 0 0 0
0 1 1 0 0 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 0 0 0 1
Then, “+/” means “reduce by addition”, yielding a frequency count of each letter in the argument:
+/e. ‘foobar’
1 2 2 1 1 1
[sourcecode]
Now, finding the first occurrence of a letter that occurs only once within the string is done by finding the first index of 1. This is done by the "index" operator "i.", the left argument of which is the data to be indexed, and the right argument is the value to index. However, since the value is already on the right side, we need to also use "reflex" (~) to switch the arguments:
[sourcecode lang="j"]
1 i.~ +/e. ‘foobar’
0
This means that the letter at index 0 (origin zero) is the first letter that has no other occurrences.
Now, we need to use that index, and produce both the letter and the index as a result.
Before we do that, however, we also need to consider the case where the index is out of range (where there are no singleton letters). This is done with a brute force “if-then-else” control structure. Many advanced J programmers try to avoid using these explicit control structures, but that’s not a goal for this exercise.
The sentence below is the final result of the “ffs” function, producing the “boxed” pair: the letter and its index, or, an empty value (where there is no singleton letter in the string).
if. (n>:#y) do. (0$0) else. ((n{y);n) end.
By aks on May 2, 2013 at 6:18 AM
A solution in Factor:
http://re-factor.blogspot.com/2013/05/non-repeating.html
By John Benediktsson on May 2, 2013 at 3:22 PM
print “enter a string”
string=raw_input(“str:”)
b=list(string)
print b
for i in b:
a=b.count(i)
if a==1:
print i
break
By anwesh on May 3, 2013 at 6:46 AM
[…] Question is from here. […]
By First Unrepeated Character In A String (Java) | Exploring Java world on May 3, 2013 at 9:03 AM
My java solution here.
By javabloggi on May 3, 2013 at 9:04 AM
My solution here: https://github.com/gepoch/praxis/blob/master/2013/april/first_unrepeated.py
It turned out to be very similar to Josh’s. but sets make it speedier.
By George on May 6, 2013 at 1:42 AM
o(2n) run time:
https://github.com/ootz0rz/tinkering-and-hacking/blob/master/~Practice/~ProgrammingPraxis/2013-04-30/main.py
By theootz on May 9, 2013 at 2:30 AM
My none-to-ambitious Ruby solution:
def first_unique(str) first_unique = str.each_char.select{|c| str.index(c) == str.rindex(c)}[0] return if first_unique.nil? [first_unique, str.index(first_unique)] endBy trojanfromnormandy on May 17, 2013 at 2:16 AM
int _holder = 0;
Console.Write(“\n Enter a string: “);
string _input = Console.ReadLine().Replace(” “, “”);
Console.Write(“\n”);
for (int i = 0; i ” + i + ” index. \n”);
}
}
Console.ReadLine();
}
//METHODS
public static int RunCheck(char entry, string input)
{
int _count = 0;
for (int i = 0; i < input.Length; i++)
{
if (entry == input[i])
{
_count = _count + 1;
}
}
return _count;
}
By Alcriss on May 24, 2013 at 6:14 AM
c#:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(“Input string: “);
string _xString = Console.ReadLine();
for (int i = 0; i < _xString.Length; i++)
{
int _count = 0;
for (int x = 0; x < _xString.Length; x++)
{
if (_xString[i] == _xString[x])
{
_count++;
continue;
}
}
if (_count == 1)
{
Console.WriteLine("Character with 1 count: " + _xString[i]);
}
}
Console.ReadLine();
}
}
}
By jaysonsoi on May 24, 2013 at 6:18 AM
here my solution with groovy :
def word=’aaggbbccffrrrrttttuuiiooppzzq’
def chars=[]
word.each{c->
if (chars.contains(c)) chars.remove(c);
else chars << c;
}
if (chars.size())
println chars[0] + " position : " + word.indexOf(chars[0])
else println "no result found"
hope will help
By hakim on June 11, 2013 at 8:19 PM
My Java Solution:
public static void firstUnrepeatedChar(String str) {
for (int i = 1; i < str.length(); i++) {
if (str.charAt(i) != str.charAt(str.length() – 1)) {
if (str.charAt(i) != str.charAt(i – 1)
&& (str.charAt(i) != str.charAt(i + 1))) {
System.out.println(str.charAt(i) + " " + i);
}
} else if (str.charAt(i) == str.charAt(str.length() – 1)
&& str.charAt(i) != str.charAt(i – 1)) {
System.out.println(str.charAt(i) + " " + i);
}
else{
System.out.println("none unrepeated");
}
}
}
By Abrar A. Shareef on August 23, 2013 at 5:38 PM
My C# solution:
class FindFirstUnRepeatedCharInGivenString
{
public string MyString { get; set; }
public FindFirstUnRepeatedCharInGivenString(string mystring)
{
MyString = mystring;
}
public char Find()
{
var IsRepeatingCharacter = true;
SortedSet set = new SortedSet();
for (int i = 0; i < MyString.Length; i++)
{
IsRepeatingCharacter = set.Add(MyString[i]);
if (!IsRepeatingCharacter)
{
return MyString[i];
}
}
return String.Empty.ToCharArray().FirstOrDefault();
}
}
By Preethi on January 29, 2014 at 9:20 AM
[…] Fist non repeating character not case sensitive programming praxis […]
By JavaScript, CSS: interview questions | EugeneBichel's Blog on October 1, 2015 at 1:00 PM