Interview Question


Country: United States




Comment hidden because of low score. Click to expand.
1
of 1 vote

public boolean anagrams(String a, String b)
{
if(a.length()!=b.length())
{
return false;
}
int [] letter=new int[256]; //assumption that character set was ASCII
char[] tmp=a.toCharArray();
for(char c:temp)
{
letter[c]++;
}
for(int i=0;i<b.length();i++)
{
int c=(int)b.charAt(i);
if(--letter[c]<0)
{
return false;
}
}
return true;
}

- Anshul August 08, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

There is one flaw with this solution, what if the 2 strings contain the same letters but in different amounts?

"An anagram is a type of word play, the result of rearranging the letters of a word or phrase to produce a new word or phrase, using all the original letters exactly once"

So this would break your solution, which would return true.
str1 = "aaabbbccc"
str2 = "abc"

You need at least one more pass to check if there are any non-zero entries in your array.

This is essentially how I would do it with hashes in ruby

list1 = "this was it"
list2 = "it was this"
h = new Hash

list1.each do | s |
	if h.containsKey(s)
		h[s] = h[s] +1
	else
		h[s] = 1
	end
end

list2.each do | s |
	if h.containsKey(s)
		if h[s] - 1 < 0
			return false
		end
		h[s] = h[s] - 1
	else
		return false
	end
end

# one last step to go through values in hash and make sure they are all 0
# since each key is unique we only need to check each letter once for count

list1.unique.each do | s |
	if h[s] != 0
		return false
	end
end

return true

Making the solution O(n+n+m) where m is less then n so essentially O(n). Probably better space storage as well since we aren't storing 256 only letters that are used in the string.

- Devils Advocate August 09, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Your actually right since the first part you check they are same size, I missed that lol but here is a second solution, that should have the size check like you did instead of the second loop through :P

- Devils Advocate August 09, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

1.sort the both string and in one loop compare each character, if each character matches, then both strings are anagram of each other. Time Complexity O(nlogn), Space complexity O(1)
2. Create a hashmap with key as character and value as counter. Traverse the first string and insert character in map if it does not exist, otherwise increment the counter.
Now, for second string, loop through each character, and search in the map and if any character does not exist, then return false, if exists then reduce the value of that key. once looping over second string is over, iterate through hashmap and all values stored in the map should be zero. then return true, otherwise return false.

- OTR August 07, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

psudo code:

bool isAnagram(char *str1, char *str2)
{
if (strlen(st1) != strlen(str2))
return false;
int charIndex[256] = {0};
int i = 0;
while (*str1 != '\0') {
charIndex[*str1] += 1;
charIndex[*str2] -= 1;
str1++, str2++;
}
while (i < 256) {
if (charIndex[i] != 0) {
return false;
}
i++;
}
return true;
}

- psych August 07, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

After compare the nth element in second array, and if it found then we should replace that element in second array with the nth element in the same array. By this way next time the second array will reduce.

str1[0] == str2[10], then replace str2[0] by str2[10] and so on.

- solanki3007 August 10, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

what about the next algo

char sum = 0;
for(int i = 0;i < strlen(s1);i++) {
	sum += (s1[i] ^  s2[i]);
}

if(sum == 0 )
	return true;
else 
return false;

So if s1 is just only permutation of s2 characters it meants that each symbol c1 in s1 has equal in s2. So c1 xor c2 == 0.

- glebstepanov1992 August 07, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I'm not sure I understand this solution. Here's a counterexample:

s1 = "ab"
s2 = "ba"

a xor b = 1
b xor a = 1

So the sum = 2 which returns false? Maybe you meant to sort the strings first but that is the largest factor in the runtime.

- wgestrich August 07, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Oh,thanks. I've found a mistake in my solution.
Actually i meant that

char sum = 0;
for(int i = 0;i< strlen(s1);i++){
	sum ^= s1[i];
	sum ^= s2[i];
}

So each element of s1 which present in s2 will exclude both from sum by xor. It was my idea.

- glebstepanov1992 August 07, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

So a ^ b ^ a ^ b == 0 in your example. It will be always true because the order of xor doesn't matter.

- glebstepanov1992 August 07, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

xor may not work all cases..let us take 'abb' and 'acc'. Accoding to xor logic they are anagrams but they are not actually..

- Siva Krishna August 08, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

1. Check if the lengths are same. If so, continue to step 2, else return false.
2. Insert each character of first string into std::set<char>. This is C++ specific. Other languages might be having counterpart of set.
3. Iterate through each character of second string and do a std::set::find on the set created in step 2.
4. If std::set::find returns std::set::end at any time during iteration, then result is false and break the loop. Else return true.

Complexity nlogn

- bibbsey August 08, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Counter example:
s1 = "aab"
s2 = "abb"

- Anonymous August 08, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

oopsie... correct.
In that case, instead of find, we can do an erase. If erase returns "not found" error then it's not an anagram. And set does not allow duplicates. In order to support your example, we have to use multi set. Still complexity remains nlogn

- bibbsey August 08, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int main()
{ int z=0,y=0,c=0,p,i,q;
char s1[]="ram is going to agra";
char s2[]="agra to going is ram";
if((q=strlen(s1))!=strlen(s2))
{printf("false");
}
p=q-1;
for(i=0;i<p;i++)
{
z+=s1[i];
y+=s2[p-i];
printf("%d, %d\n",z,y);
if((s1[i]==' '&&s2[p-i]==' '))
{ c++;
if(z==y)
{ c--;}
z=0;
y=0;
}
}
printf("%d",c);
if(c==0)
{printf("string is panagram");}
else{printf("not");}
system("pause");
}

- ratnakar.ps1077 August 09, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

The most efficient algo is actually going to depend on the size of your character set relative to the size of the string, there is a way to do it in O(n) time with O(1) space(much less than a hash map), you simply use the concept of "buckets", here is the code in Java:

import static org.junit.Assert.*;

import org.junit.Test;


public class AnagramFinder {

	public static boolean areAnagrams(String s1, String s2) {
		if(s1.length() != s2.length())
			return false;
		//Assume ascii set
		int[] s1Counts=new int[256];
		int[] s2Counts=new int[256];
		
		for(int i=0;i<s1.length();i++) {
			s1Counts[s1.charAt(i)]++;
			s2Counts[s2.charAt(i)]++;
		}
		
		for(int i=0;i<s1Counts.length;i++) {
			if(s1Counts[i] != s2Counts[i])
				return false;
		}
		return true;
	}
	
	@Test
	public void testAreAnagrams() {
		assertTrue(areAnagrams("that","hatt"));
	}
	@Test
	public void testNotAnagrams() {
		assertFalse(areAnagrams("that","hart"));

	}
	
}

This is faster and takes less space than the hashmap(though both are O(n) time and O(1) space, in practice the above is faster), but this tends to fall apart if you have larger char sets.

Another even less practical(though more space efficient) method is to assign each letter a prime value('a' is 2, 'b' is 3, 'c' is 5 etc) then multiply all those together. This just requires 2 BigNumber objects(and a lookaside table to translate the characters into their primes)....theoretically if you had to calculate a lot of anagrams simultaneously with a large ROM but very little RAM you could use that method, but somehow I doubt that's really practical :P

- Joel Tucci August 09, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

thats nice, but your idea is based on ASCII alphabet. How about if you using UTF16. a lot of languages and characters, So it means that your memory grows O(n), not the O(1).

- glebstepanov1992 August 09, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Did you bother to read the comment before replying? Not only did I mention the character set TWICE, your comment is just plain wrong, memory does not grow O(n) if you use UTF-16, you still do it in constant memory, you just need a lot more of it. It has NOTHING to do with the length of the string.

- Joel Tucci August 09, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I see, but can you explain what the difference between using array,as you did and hashmap. Hash map has its own array and Character uses Objects native hashcode, that is almost unique per each object.so yo'll have nice disribution. You can also adjust size of hashmap from the begging.

- glebstepanov1992 August 09, 2013 | Flag


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More