tags:

views:

674

answers:

13

How to determine if two strings are permutations of each other

+15  A: 
  • Sort the two strings's characters.
  • Compare the results to see if they're identical.

Edit:

The above method is reasonably efficient - O(n*log(n)) and, as others have shown, very easy to implement using the standard Java API. Even more efficient (but also more work) would be counting and comparing the occurrence of each character, using the char value as index into an array of counts.

I do not thing there is an efficient way to do it recursively. An inefficient way (O(n^2), worse if implemented straightforwardly) is this:

  • If both strings consist of one identical character, return true
  • Otherwise:
    • remove one character from the first string
    • Look through second string for occurrence of this character
    • If not present, return false
    • Otherwise, remove said character and apply algorithm recursively to the remainders of both strings.
Michael Borgwardt
can't use sort.can u give me code for recursion?
Supratim
can u give me the code for this?
Supratim
what about a hash-map?Can u give me code on that regarding this prob?
Supratim
A hash map would not be helpful. And I will not do your work for you.
Michael Borgwardt
hey mike,can u give me java code for that algo?
Supratim
@Supratim: how do you want to pass the class if you only want the code? You're supposed to write it and if you can't then you will (and should!) fail the class.
Joachim Sauer
a hash map could be helpful, or even just a 26 element array of int. you can create a histogram of each string and compare those for equality. O(n) runtime but O(n) extra storage.
jk
i don't recall talking to u--Joachim.
Supratim
i need the code in java, JK.Can u help me with that?
Supratim
@jk yeah, I meantioned that option, though I would not assume the input consists only of unaccented latin letters.
Michael Borgwardt
@Supratim People will gladly help you with any specific problems you have getting *your* solution to work. But they will not hand you ready-made code. Joachim is entirely right in what he said. If you want others to do your homework assignments for you, do everyone a favor and drop out of school right away; the net effect will be the same as if you continue like this.
Michael Borgwardt
well mike,have u seen the code not so long ago?however,seems like u guys are positively going to get me back to school.
Supratim
the prob is with that code is --how do i get those two strings to compare to each other?
Supratim
i pasted a code -mike--check it out.c if u can help me after this.
Supratim
well mike ,anything on the code?
Supratim
Well, you've pasted the code other people wrote in their answers. You have not tried to implement the recursive method I described above.
Michael Borgwardt
sorry,where is this code written?
Supratim
really,mike,like i said,u guys are too smart.anyway,thanx for evrything.
Supratim
+5  A: 

To put @Michael Borgwardt's words in to code:

if(str1.length != str2.length)
  return false;

char[] a = Arrays.sort(str1.toCharArray());
char[] b = Arrays.sort(str2.toCharArray());
int len = a.length;

for(i = 0; i < len; ++)
  if(b[i] != a[i])
    return false;

return true;
Amarghosh
There's also Arrays.equals() for the last step. But the idea was not to give readymade code for an obvious homework question.
Michael Borgwardt
@Supratim: what do you think you've been given here? A great suggestion on how to do it *and* the code.
Joachim Sauer
And someone down-voted me for giving away the full code for a homework question.
Amarghosh
@Amarghosh: I tend to agree that giving full code here is not a good service (didn't downvote, 'though). In this case not even the OP seems to thank you for it.
Joachim Sauer
@Joachim I see your point - I was rep-whoring to hit 8K ASAP I guess ;)
Amarghosh
Do you mean that your teacher wants you to use recursion in solving this? I am not gonna repeat the mistake of giving away the ready made code for homework again.
Amarghosh
Thanks for specifying all these requirements in question and thanks for being so nice to me even though I couldn't come up with anything you asked for in the question. I'll try to avoid being unhelpful like this in the future. @Joachim You were right.
Amarghosh
@Amarghosh: Just got to see this thread I don't know where I clicked that brought me this thread. Anyways, a suggestion, you might appreciate. 1. As Joachim said, "Its not a good idea to give away the full code, its bad for students". 2. Don't do it in the respect of folks who decided not to give the full code, especially when they are seniors (of course age doesn't matter here, nor repo).
Adeel Ansari
+3  A: 
  1. Sort the 2 strings by characters and compare if they're the same (O(n log n) time, O(n) space), or
  2. Tally the character frequency of the 2 strings and compare if they're the same (O(n) time, O(n) space).
KennyTM
Actually, the space required is `O(1)` in the second case - 2**16 ints.
Stephen C
That's a bad O(1) ;) And I could use a hash table.
KennyTM
In the worst case a hash table is significantly more that 2**16 words. But yes, a hash table would be better in typical cases and also `O(1)` in space / time. BTW - you haven't fixed the error yet ...
Stephen C
+1  A: 

Create a Hashmap with the characters of the first string as keys and the number of occurances as value; then go through the second string and for each character, look up the hash table and decrement the number if it is greater than zero. If you don't find an entry or if it is already 0, the strings are not a permutation of each other. Obviously, the string must have the same length.

ammoQ
Can u please give me the Javacode using hashmaps for this problem?Thanx
Supratim
Supratim: There is a consensus here at SO that we should not do homework for others. Giving you the code would get me downvoted.
ammoQ
i already did it .check the code pasted below.
Supratim
not my problem.
ammoQ
what i meant ammoQ,what do u think about the code?
Supratim
is it ok?if not what's the prob?
Supratim
I won't comment on somebody else doing you homework, sorry.
ammoQ
+1  A: 

You might take a look at String.toCharArray and Arrays.sort

JRL
can't use sorting.got to use hash maps or recursion.can u help me with that?
Supratim
@Supratim: there are already other answers that make use of a hashmap or recursion. What's wrong with them?
JRL
i need the code.i am new to java.and i will port the code to c++.The java code i need.
Supratim
can u help me with it?
Supratim
+1  A: 

First you check the lengths (n), if they are not same, they cannot be permutations of each other. Now create two HashMap<Character, Integer>. Iterate over each string and put the number of times each character occur in the string. E.g. if the string is aaaaa, the map will have just one element with key a and value 5. Now check if the two maps are identical. This is an O(n) algorithm.

EDIT with code snippet :

boolean checkPermutation(String str1, String str2) {

char[] chars1 = str1.toCharArray();
char[] chars2 = str2.toCharArray();

Map<Character, Integer> map1 = new HashMap<Character, Integer>();
Map<Character, Integer> map2 = new HashMap<Character, Integer>();

for (char c : chars1) {
   int occ = 1;
   if (map1.containsKey(c) {
       occ = map1.get(c);
       occ++;
   }
   map1.put(c, occ);
}

// now do the same for chars2 and map2

if (map1.size() != map2.size()) {
   return false;
}
for (char c : map1.keySet()) {

    if (!map2.containsKey(c) || map1.get(c) != map2.get(c)) {
        return false;
    }
}

return true;
}
fastcodejava
can u give me the javacode for this plz?
Supratim
Is a homework! The idea is that you solve it by yourself, in order to learn.
JuanZe
not homework.can u do it for me
Supratim
nice,but i cannot get the code to work,and where is the user input for the strings?
Supratim
i think there is also some problem with the method declaration.
Supratim
what do u think?
Supratim
Supratim
I don't why you are so hung up on the input part? Somebody has already give a solution below using BufferedReader : BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
fastcodejava
if u implement that using bufferred reader with this code u will understnd what i am talking about.why don't u have a go?and how about making the strings mutable.
Supratim
Personally, I consider any Java answer bunk unless they make the strings mutable. What good is an answer if they don't attempt to completely restructure the underlying language at the same time?
dimo414
A: 

This is the way using sort.but i got to use recursion.

import java.io.*; import java.util.Arrays;

public class perm { public static void main(String[] args) throws IOException {

    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 

    System.out.print("First string: "); //Input 1st string
    String str1 = reader.readLine(); 
    System.out.print("Second string: "); //Input 2nd string 
    String str2 = reader.readLine(); 

    char[] chars1 = str1.toCharArray(); 
    char[] chars2 = str2.toCharArray(); 

    Arrays.sort(chars1); 
    Arrays.sort(chars2); 
    System.out.println("Second is a permutation of first:" + Arrays.equals(chars1, chars2));//Return true if permutation,return false if not. 
} 

}

Supratim
hey bill,can u help me with this code using recursion?
Supratim
A: 

I'm working on a Java library that should simplify your task. You can re-implement this algorithm using only two method calls:

boolean arePermutationsOfSameString(String s1, String s2) {
    s1 = $(s1).sort().join(); 
    s2 = $(s2).sort().join();
    return s1.equals(s2);
}

testcase

@Test
public void stringPermutationCheck() {
    // true cases
    assertThat(arePermutationsOfSameString("abc", "acb"), is(true));
    assertThat(arePermutationsOfSameString("bac", "bca"), is(true));
    assertThat(arePermutationsOfSameString("cab", "cba"), is(true));

    // false cases
    assertThat(arePermutationsOfSameString("cab", "acba"), is(false));
    assertThat(arePermutationsOfSameString("cab", "acbb"), is(false));

    // corner cases
    assertThat(arePermutationsOfSameString("", ""), is(true));
    assertThat(arePermutationsOfSameString("", null), is(true));
    assertThat(arePermutationsOfSameString(null, ""), is(true));
    assertThat(arePermutationsOfSameString(null, null), is(true));
}

PS

In the case you can clone the souces at bitbucket.

dfa
nice,but can u give me complete code of the same problem using hash--map?Thanx anyway.
Supratim
why a hash-map? imho it is the wrong data structure for this problem
dfa
becoz i have to use hash map.otherwise the arrays.sort was the best method.
Supratim
can u give code using hashmaps?Thanx
Supratim
$(s1).sort() does exactly Arrays.sort() internally
dfa
thtat's the prob,can't use sorting.Have to do it some other way--recursion or hash-map will do.can u plz give me completed java code on this one?thanx.
Supratim
A: 

The obligatory Guava one-liner:

boolean isAnagram(String s1, String s2) {
    return ImmutableMultiset.copyOf(Chars.asList(s1.toCharArray())).equals(ImmutableMultiset.copyOf(Chars.asList(s2.toCharArray())));
}

(Just for fun. I don't recommend submitting this for your assignment.)

finnw
@Supratim: do you want to be an engineer or a manager? If you want to be an engineer, you're supposed to consider and solve technical problems by yourself. You can ask for help but you're supposed to synthesize and understand the solution yourself.
reinierpost
the prob is,i am already a manager.
Supratim
but thanx for the help anyway.
Supratim
A: 

import java.io.*;

class Permutation {

public static void main(String args[]) throws IOException {
BufferedReader br = 
new BufferedReader(new InputStreamReader(System.in));
String str,newstr;
System.out.println("enter the string");
str = br.readLine();
System.out.print("The permutations are :");
int len = str.length();
StringBuffer sb = new StringBuffer(str);
    if(len <=1){
System.out.print(str);
    }
else doPerm(sb,len);
    System.out.println("");
    System.out.println("enter the 2nd string");
    newstr = br.readLine();
    if(newstr.equalsIgnoreCase(str)){
        System.out.print("Permutation");
    }
}   

private static void doPerm(StringBuffer str,int index){

    if(index > 2){
doPerm(str,index-1);
}
else{
swap(str);
return; 
}
int len1 =  str.length(); 
StringBuffer s1=new StringBuffer(str);
for(int j = 0;j < index-1; j++){
char t1 = s1.charAt(len1-1-j);
char t2 = s1.charAt(len1-index);
s1.setCharAt(len1-1-j,t2);
s1.setCharAt(len1-index,t1);
doPerm(s1,index-1);
    }
    }

//Swap the last two chars
private static void swap(StringBuffer d){
//Print given String first  
System.out.print(d);
System.out.print("  ");
int length=d.length();
char t1,t2;
t1=d.charAt(length-1);
t2=d.charAt(length-2);
d.setCharAt(length-1,t2);
d.setCharAt(length-2,t1);
System.out.print(d);
System.out.print("  ");
d.setCharAt(length-1,t1);
d.setCharAt(length-2,t2);
}

}

I am doing it this way.now how can i get the strings to be compared to each other?can anyone help me with that?

Supratim
Did you say it has to be fast? If so then it is a bad idea to try to generate all permutations.
finnw
A: 

As you requested, here's a complete solution using recursion. Now all you have to do is:

  1. Figure out what language this is
  2. Translate it to Java.

Good luck :-)

proc isAnagram(s1, s2);
  return {s1, s2} = {''} or
         (s2 /= '' and
          (exists c = s1(i) |
                  s2(1) = c and
                  isAnagram(s1(1..i-1) + s1(i+1..), s2(2..))));
end isAnagram;
finnw
proc-end is also there in eye-OS
Supratim
Poor syntax highlighter got crazy)
Rorick
Not the most efficient method though.
reinierpost
is it TCL,@reinierpost
Supratim
There is also a HP 9000 computers assembler directive like this.However i don't think it is that.
Supratim
I think it is ruby.Well finnw?
Supratim
You're obviously not going to guess it. It's SETL.
finnw
never used it,so how am i supposed to know?
Supratim
however,surprised that u still using SETL instead of ProSet,finnw
Supratim
I am not aware of any public release of ProSet
finnw
A: 

import java.io.*; public class permuterecur {

 public static void main(String[] args) throws IOException {         

String a,b; 

    BufferedReader br = 
        new BufferedReader(new InputStreamReader(System.in));
   System.out.println("enter the 1st string");
a = br.readLine();
System.out.println("enter the 2nd string");
b = br.readLine();
    if (a.length() != b.length()) { 
    System.out.println("Not permutation"); 
} 

int[] charCount = new int[256]; 
for (int i = 0; i < a.length(); ++i) { 
    ++charCount[a.charAt(i)]; 
} 

for (int i = 0; i < b.length(); ++i) { 
    if (--charCount[b.charAt(i)] < 0) { 
        System.out.println("Not permutation"); 
    } 
} 
 System.out.println("permutation"); 

} } I am using this code.But there seems to be a problem with it.it prints"permutation"even when the two strings are not.Any comments?

Supratim
Add a check at the end whether all remaining charCounts are 0.
reinierpost
can u write down that line of code for me plz?
Supratim
If you were able to write this code, you should also be able to write the final part that checks the remaining counts are all 0. Did you really write this or did you copy it from a fellow student?
finnw
forget about it.i will write it myself.U people really take the cake.
Supratim
AND FOR THE LAST TIME----U ARE NOT TALKING TO A STUDENT,by the way.
Supratim
anyway,who needs u people?
Supratim
And where did the array size of 256 come from? It's not large enough to cover all `char` values but it's twice as big as you need if you only accept ASCII. So you probably want either `Byte.MAX_VALUE + 1` or `Character.MAX_VALUE + 1`.
finnw
i need to accept only ASCII
Supratim
Since i don't use a dictionary but the array,accessing the index should be much faster.
Supratim
Maybe you're not a student, but you are an asshole. No one on this site owes you anything. You should be thanking all these people for taking the time to answer your question, not scolding them for not doing enough of your job for you.
dimo414
A: 

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;

public class permutcheck {

 public static void main(String[] args) throws IOException {         

String a,b; 

    BufferedReader br = 
        new BufferedReader(new InputStreamReader(System.in));
   System.out.println("enter the 1st string");
a = br.readLine();
System.out.println("enter the 2nd string");
b = br.readLine();
    if (a.length() != b.length()) { 
    System.out.println("Not permutation"); 
} 
int[] charCount = new int[256]; 
for (int i = 0; i < a.length(); ++i) { 
    ++charCount[a.charAt(i)]; 
} 

for (int i = 0; i < b.length(); ++i) { 
    if (--charCount[b.charAt(i)] < 0) { 
        System.out.println("Not permutation"); 
    } 
} 

System.out.println("permutation"); 

}
}

i used this code--but it is case-sensitive.how can i make it case-insensitive

Supratim
can anyone help me?
Supratim