17

Is there a way to check if two strings contain the same characters. For example,

abc, bca -> true
aaa, aaa -> true
aab, bba -> false
abc, def -> false
codaddict
  • 445,704
  • 82
  • 492
  • 529
Brent
  • 181
  • 1
  • 2
  • 5
  • possible duplicate of [Checking if two strings are permutations of each other](http://stackoverflow.com/questions/2131997/checking-if-two-strings-are-permutations-of-each-other) – finnw Oct 21 '10 at 09:07

13 Answers13

29

Turn each string into a char[], sort that array, then compare the two.

private boolean sameChars(String firstStr, String secondStr) {
  char[] first = firstStr.toCharArray();
  char[] second = secondStr.toCharArray();
  Arrays.sort(first);
  Arrays.sort(second);
  return Arrays.equals(first, second);
}
chris Frisina
  • 19,086
  • 22
  • 87
  • 167
GaryF
  • 23,950
  • 10
  • 60
  • 73
  • ...and remove duplicates before comparing – testalino Oct 21 '10 at 07:55
  • 9
    No, if we were removing duplicates then "aab, bba" would return true and it's specified as returning false. – GaryF Oct 21 '10 at 07:56
  • 1
    `Arrays.equals`, not `equal`. – aioobe Oct 21 '10 at 08:01
  • Thank you very much. It was simpler than I had thought. I'm surprised this isn't already a method inside the String class. – Brent Oct 21 '10 at 08:06
  • 1
    @Brent: re: not already a method-- really? :) I have never needed to do this particular task in a decade of professional string manipulation. Plus little problems like this are nice to keep in the fun domain of interview questions and Stack Overflow quickies over morning tea. – Ben Zotto Oct 21 '10 at 08:17
  • 1
    Note that the return line needs a semicolon. I attempted to edit it, but I can't make an edit of fewer than 6 characters, and nothing else needs modification. – Jake Mar 28 '16 at 16:30
  • 1
    @Jake I can. Fixed. Well done on spotting a 5-year+ mistake. – GaryF Mar 29 '16 at 19:00
8

A very easy - but not very efficient - way to do that is, convert your Strings to char arrays and use java.util.Arrays.sort on them, get Strings back and compare for equality. If your strings are under a few thousand characters, that should be very okay.

If you have several megabytes strings, you may want to create an array with a count for each character (using its code as an index), have one pass on one string adding one on the count of each char, and one pass on the second string removing one. If you fall under 0 at any point during the second pass, they don't have the same characters. When you're done with the second string without error, you are sure they have the same characters if they have the same length (which you should have checked first anyway).
This second method is much more complicated than sorting the strings, and it requires a big array if you want to work with unicode strings, but it's perfectly good if you're okay with only the 128 chars of the ascii set, and much faster.
Do NOT bother with that if you don't have several million characters in your strings. Sorting the strings is much easier, and not significantly slower on strings with only a couple dozen chars.

Jean
  • 10,545
  • 2
  • 31
  • 31
3

As a (nitpicking ;-) ) side note:

Be aware that the solutions proposed here only work for strings composed of characters from the Basic Multilingual Plane (BMP) of Unicode.

Characters outside the BMP are represented as a pair of char in a String, so you need to pay extra attention, so you keep the pairs together. See the Javadocs of java.lang.Character for the gory details.

Fortunately, most characters outside the BMP are rather exotic. Even most of Japanese and Chinese is in the BMP...

sleske
  • 81,358
  • 34
  • 189
  • 227
  • Actually, the solutions here will work outside the BMP just fine. The problem is that they won't work on non-normalized strings; the issue is that "é" can be written as either a single character or a composition of "e" and an accent. (This is a problem for a number of European languages, and few others too.) – Donal Fellows Oct 21 '10 at 08:17
  • @Donal Fellows: How can they work outside the BMP? A character from outside the BMP will be represented as a pair of surrogates, i.e. as two `char`.If you then invoke e.g. `Arrays.sort(chars1)`, the sort function, which does not know about surrogates, will happily tear apart the surrogates and produce junk data. Or am I missing something? – sleske Oct 21 '10 at 08:37
  • @Donal Fellows: But of course you are right that the problem will also occur with combining characters. And BTW, using a normalized string is not enough, because there are several different normalizations, and some use combining characters. – sleske Oct 21 '10 at 08:41
  • re non-BMP: Damn, just realized that I'm wrong as it's possible to have two non-BMP character groups confused. I doubt it will happen in practice at the moment though; the amount of non-BMP characters defined and in use is fairly small and they're typically sparsely used. A normalized string is enough, but everything must be normalized the same way (i.e., to NFC or NFD, not a mix!) – Donal Fellows Oct 21 '10 at 09:13
  • NFC will *not* work. It will decompose characters, and then you'll compare the decomposed parts individually. That would mean that e.g. aé and áe would compare as equal, as both decompose to "acute", "a", "e". This is (probably) not what is intended. Just goes to show that Unicode (rather, characters sets in general) has its pitfalls... – sleske Oct 21 '10 at 09:49
3

Maybe it's not the fastest answer, but it must be shortest answer.

boolean hasSameChar(String str1, String str2){
  for(char c : str1.toCharArray()){
    if(str2.indexOf(c) < 0 ) return false;
  }
  for(char c : str2.toCharArray()){
    if(str1.indexOf(c) < 0 ) return false;
  }
  return true;
}
TruVortex_07
  • 280
  • 1
  • 3
  • 16
guilin 桂林
  • 17,050
  • 29
  • 92
  • 146
2

Consider creating a signature for a given String. Using count and character.

a-count:b-count:c-count:.....:z-count: (extend for upper case if you want ).

Then compare the signature. This should scale better for very large Strings.

As a shortcut, check the length. If they are not matching, return false anyway.

Jayan
  • 18,003
  • 15
  • 89
  • 143
1

You can convert the string into char array, sort the arrays and them compare the arrays:

String str1 = "abc";                 
String str2 = "acb";
char[] chars1 = str1.toCharArray();
char[] chars2 = str2.toCharArray();
Arrays.sort(chars1);
Arrays.sort(chars2);

if(Arrays.equals(chars1,chars2)) {
        System.out.println(str1 + " and " + str2 + " are anagrams");
} else {
        System.out.println(str1 + " and " + str2 + " are not anagrams");
}
codaddict
  • 445,704
  • 82
  • 492
  • 529
0

Here:

import java.util.Arrays;

public class CompareString {

String str = "Result";
String str1 = "Struel";

public void compare() {
    char[] firstString = str.toLowerCase().toCharArray();
    char[] secondString = str1.toLowerCase().toCharArray();

    Arrays.sort(firstString);
    Arrays.sort(secondString);

    if (Arrays.equals(firstString, secondString) == true) {
        System.out.println("Both the string contain same charecter");
    } else {
        System.out.println("Both the string contains different charecter");
    }
}

public static void main(String[] args) {
    CompareString compareString = new CompareString();
    compareString.compare();
}

}

Siba
  • 7
  • 2
0

here:

    String str1 = "abc";
    String str2 = "cba";
    /* create sorted strings */

/*  old buggy code
    String sorted_str1 = new String( java.utils.Arrays.sort(str1.toCharArray()) );
    String sorted_str2 = new String( java.utils.Arrays.sort(str2.toCharArray()) );
*/    
/* the new one */
char [] arr1 = str1.toCharArray();
char [] arr2 = str2.toCharArray();
java.utils.Arrays.sort(arr1);
java.utils.Arrays.sort(arr2);
String sorted_str1 = new String(arr1);
String sorted_str2 = new String(arr2);

if (sorted_str1.equals( sorted_str2 ) ) {
        /* true */
    } else {
        /* false */
    }
Erhan Bagdemir
  • 5,231
  • 6
  • 34
  • 40
  • 1
    Arrays.sort(..) has a return type of void, so you cannot use it directly in the String constructor. – GaryF Oct 21 '10 at 08:01
0

This problem can be simply solved in O(n) time and O(1) space. The idea is to use a temp array of size 26 as we have only 26 characters in the alphabet.

First, if length of both strings are different we immediately return false. We iterate over length of the given string and in temp array, increase frequency of every character in string one and decrease count of character occured in other string. At the end temp array should have 0 count for every character if strings have equal characters.

auspicious99
  • 3,902
  • 1
  • 44
  • 58
0

Agree to what @Jean says above for an efficient solution using HashMap. This problem is also called Anagram. Below is the solution in Scala.

Note: cleanString is where whitespaces are removed and all characters are lowercase

def isAnagram(cleanString1, cleanString2) = {
  createHashMap(cleanString1) == createHashMap(cleanString2)
}

def createHashMap(str: String): immutable.HashMap[Char, Int] = {
  str.foldLeft(immutable.HashMap.empty[Char, Int]) { (acc, next)
  => if (acc.contains(next)) acc + (next -> (acc(next) + 1)) 
     else acc + (next -> 1)
     }
}
0
public static boolean isSameLetters(String word1, String word2){
    String s1 = Arrays.stream(word1.trim().strip().replaceAll("\\s","").split("")).sorted().collect(Collectors.joining());
    String s2 = Arrays.stream(word2.trim().strip().replaceAll("\\s","").split("")).sorted().collect(Collectors.joining());
    System.out.printf("word 1: %s\nword 2: %s\n",s1,s2);
    return s1.equals(s2);
}
0

//C++

#include<bits/stdc++.h>
using namespace std;

string cmpstr(string &s1,string &s2){

map<int,int>m1;
map<int,int>m2;

for(auto &c:s1)m1[c]++;
for(auto &c:s2)m2[c]++;

return m1==m2?"true":"false";


}
int main(){
    string s1,s2;
    cin>>s1>>s2;
    cout<<cmpstr(s1,s2);
    return 0;
}
prashant
  • 11
  • 3
  • 1
    The OP has clearly indicated that Java is the programming language in which he is looking for solution not C++. – Peter Csala Jan 31 '22 at 07:47
0
public static void main(String[] a) {
        String s1 = "bore", s2 = "robe";
        char[] ch1 = s1.toCharArray();
        Arrays.sort(ch1);

        char[] ch2 = s2.toCharArray();
        Arrays.sort(ch2);
        System.out
                .println("Using array comparision method,Both strings contains same chars :" + Arrays.equals(ch1, ch2));

        String s11 = new String(ch1);
        String s22 = new String(ch2);
        System.out
                .println("Using String equals method,Both strings contains same chars : :" + s11.equalsIgnoreCase(s22));
    }

Here I have used Arrays & String class methods. Whatever comes at first in you mind you can use that. If comparison is the only purpose then use Arrays method and avoid creating string.

If you want o/p in string then anyway you will have to create strings.

Shivi
  • 91
  • 1
  • 4