9

I would like to make anagram algorithm but This code doesn't work. Where is my fault ? For example des and sed is anagram but output is not anagram Meanwhile I have to use string method. not array. :)

public static boolean isAnagram(String s1 , String s2)
{
    String delStr="";
    String newStr="";

    for(int i=0;i<s1.length();i++)
    {
        for(int j=0 ; j < s2.length() ; j++)
        {
            if(s1.charAt(i)==s2.charAt(j))
            {
                delStr=s1.substring(i,i+1);
                newStr=s2.replace(delStr,"");
            }
        }           
    }

    if(newStr.equals(""))
        return true;
    else
        return false;
}
OmG
  • 15,398
  • 7
  • 42
  • 71
SemihY
  • 229
  • 1
  • 3
  • 11
  • 3
    Can you explain what you are seeing wrong? Does an exception throw? Does it just not return what you expect? Does it infinite-loop? – Mike Clark Dec 03 '12 at 21:42
  • Can you give an example as to what is an `Anagram` in your case? – Rohit Jain Dec 03 '12 at 21:45
  • No, only I wrote des and sed but output is not anagram – SemihY Dec 03 '12 at 21:45
  • 2
    Why does your code not work? Because you overwrite `newStr` with `s2` (less a letter) every time you get a match. For example, if `s2` is `ab`, when you match `b`, `newStr` becomes `a`, then when you match `a`, `newStr` does not become the empty string, but becomes `b` (since it is `s2` less the matching character). It is not the only bug in your code (repeated characters, different length strings), but it is the one that you are going to see first. – Konstantin Tarashchanskiy Dec 03 '12 at 22:10
  • Probably worth noting after all this time that Java has progressed sufficiently to make this a one-liner: `Arrays.equals( a.chars().filter(Character::isAlphabetic).sorted().toArray(), b.chars().filter(Character::isAlphabetic).sorted().toArray());` – Gene Jan 13 '20 at 05:15

35 Answers35

31

An easier way might be to just sort the chars in both strings, and compare whether they are equal:

public static boolean isAnagram(String s1, String s2){

        // Early termination check, if strings are of unequal lengths,
        // then they cannot be anagrams
        if ( s1.length() != s2.length() ) {
            return false;
        }
        s1=s1.toLowerCase();
        s2=s2.toLowerCase();
        char[] c1 = s1.toCharArray();
        char[] c2 = s2.toCharArray();
        Arrays.sort(c1);
        Arrays.sort(c2);
        String sc1 = new String(c1);
        String sc2 = new String(c2);
        return sc1.equals(sc2);
}

Personally I think it's more readable than nested for-loops =p

This has O(n log n) run-time complexity, where n is the length of the longer string.

Edit: this is not the optimal solution. See @aam1r's answer for the most efficient approach (i.e. what you should actually say in an interview)

Panagiotis
  • 93
  • 1
  • 8
sampson-chen
  • 40,497
  • 12
  • 76
  • 76
  • 4
    lol. +1 You can use Arrays.equals() to compare the sorted arrays. – Peter Lawrey Dec 03 '12 at 21:47
  • @PeterLawrey: Or use a simple loop, which is equivalent. But not this – durron597 Dec 03 '12 at 21:51
  • 1
    @user1873885 Unfortunately "isn't working" does not give me any information that I can use to help you with =( – sampson-chen Dec 03 '12 at 21:54
  • @sampson-chen I don't understand problem. I write des and sed but input is not anagram. Meanwhile I dont use array class. Only string methods – SemihY Dec 03 '12 at 22:01
  • @user1873885 you need to show us the full code, particularly 1) where you are using `isAnagram`, 2) what is expected input / output and 3) what you are actually getting – sampson-chen Dec 03 '12 at 22:04
  • @user1873885 - Assuming you have fixed the braces on the `if`, your code is not working because, after each loop iteration, `newStr` is set to the result of deleting only the last match from `s2`. – Ted Hopp Dec 03 '12 at 22:07
  • @sampson-chen: I would assume abuse by user while using this function and add this check: `code` if (s1 == null || s2 == null) { return false; } `code` Else it will throw NPE when either of s1 or s2 is null. – realPK Feb 10 '14 at 22:02
  • Dear all future readers, this is by far one of the least performant answers. Do not use – durron597 Jul 22 '14 at 15:44
  • 1
    @durron597 - yup, aam1r's answer is the optimal solution, vote that one up instead. – sampson-chen Jul 23 '14 at 05:52
  • @sampson-chen could you please explain where does logn comes from? – Ömer Faruk Almalı Apr 22 '15 at 09:00
  • @ÖmerFarukAlmalı O(n log n) is from comparison-based sorting: http://en.wikipedia.org/wiki/Comparison_sort – sampson-chen Apr 23 '15 at 05:06
  • So the space complexity is O(n) due to the additional char arrays? – marlon May 13 '15 at 20:39
  • It's a little bit simpler to use `Arrays.equals` here rather than converting back to strings. https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#equals-char:A-char:A- – kaya3 Jan 21 '20 at 18:55
30

This can be done in linear time using constant space. Here is pseudo-code to help you get started:

// Create new hashtable/hashmap to keep track of how many times each character
// is being used
character_map -> new hash map

// Initial check. If lengths are not the same, they can't be anagrams.
if s1.length != s2.length:
    throw exception "Not anagrams"

// Add all characters from s1 to hashmap. Increment the value to keep track of
// number of occurences
foreach character c1 in s1:
    character_map[c1]++

// Iterate through all character in s2 and decrement count of each character.
foreach character c2 in s2:
    character_map[c2]--

// If they are anagrams, each character should be at "0" count at the point.
// If we come across a character that is not, it means that they are not anagrams
foreach key k, value v in character_map:
    if v != 0:
            throw exception "Not anagrams"

This code does not sort and hence can be done using simple loops. The overall runtime is O(n) and overall space is O(1) -- hence being the fastest solution. The number of elements you can have in the hash map is constant (i.e. you know how many items there are in your alphabet set).

Aamir
  • 5,071
  • 2
  • 27
  • 45
8
if(s1.charAt(i)==s2.charAt(j))
        delStr=s1.substring(i,i+1);
        newStr=s2.replace(delStr,"");

This code is a nice demonstration of why you should always have curly braces around your if, even if there is only a single statement. Your 2nd assignment is actually outside the if-condition, and will always happen.

The best way to check for two strings to be Anagram is to convert them to a character array (String#toCharArray). Then sort them using Arrays.sort method. And do the comparison on them.


Updated : -

If you just want to use String methods, then you don't actually need a nested loop there. You can do it with just one.

Here's the modified code of yours: -

public static boolean isAnagram(String s1 , String s2){

    if (s1.length() != s2.length()) {
        return false;
    }

    for(int i = 0; i < s2.length(); i++) {

            if( !s1.contains("" + s2.charAt(i))) {
                return false;
            }

            s1 = s1.replaceFirst("" + s2.charAt(i), "");
            s2 = s2.replaceFirst("" + s2.charAt(i), "");
    }
    return true;
}
Rohit Jain
  • 195,192
  • 43
  • 369
  • 489
  • Yeah, i agree. It is always recommended to have `curly braces` around an `if`. – andreih Dec 03 '12 at 21:44
  • @user1873885. May be. But to get it to work, you need to tell what is an `Anagram`? I can't understand the logic of the code. – Rohit Jain Dec 03 '12 at 21:45
  • @durron597 yepp, the code still doesnt work, thats why its not accepted yet :P, upvotes are for pointing the blunder in the code . – PermGenError Dec 03 '12 at 21:46
  • @durron597.. Ah! Actually, this was the only logical error that I could notice in the code, because I don't know what Anagram OP is talking about. – Rohit Jain Dec 03 '12 at 21:46
  • @GanGnaMStYleOverFlowErroR: There are now three correct answers in this thread, all of which have fewer upvotes than this answer. Rohit, you should give yourself the disciplined badge now ;) – durron597 Dec 03 '12 at 21:49
  • @durron597.. Lol.. Do you really want me to have that? :( I have updated my answer, not with some code though, as OP has already got 3 of them. – Rohit Jain Dec 03 '12 at 21:51
  • @durron597 haha, yeah, (upvotes!=accepted). and i did upvote all the 3 answers(including yours) :), however i think Rohits answer is quite useful:) – PermGenError Dec 03 '12 at 21:51
  • @durron597. There you go. I added a code, for it to be a valid answer. ;) – Rohit Jain Dec 03 '12 at 22:07
  • @RohitJain: What, you don't want a Disciplined badge? :) Also, that code doesn't work, consider the strings "abbbccc" and "aaaaabc" – durron597 Dec 03 '12 at 22:07
  • @durron597.. No :( I have always had an image of in-disciplined guy. I don't want to loose that image. – Rohit Jain Dec 03 '12 at 22:08
  • @durron597.. Let me modify it. – Rohit Jain Dec 03 '12 at 22:09
8

What would be more efficient is to compare the Strings in sorted order.

public static boolean isAnagram(String s1 , String s2) {
    return s1.length() == s2.length() 
        && checkSum(s1) == checkSum(s2)
        && Arrays.equals(lettersSorted(s1), lettersSorted(s2));
}

static long checkSum(String s) {
    long sqrSum = 0;
    for(int i = 0; i < s.length(); s++) {
       char ch = s.charAt(i);
       sqrSum += ch + (1L << ch);
    }
}

static char[] lettersSorted(String s) {
    char[] chars = s.toCharArray();
    Arrays.sort(chars);
    return chars;
}

This is an O(N ln N) algorithm, but will be O(N) on an average if the Strings are typically not anagrams.

Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
7

I'm not sure what you're trying to do, but I'm pretty sure it won't work (and it runs in O(n^2). Try this (which runs in O(n log n)) instead:

public static boolean isAnagram(String s1, String s2){
  if (s1.length() != s2.length()) return false;

  char[] c1 = s1.toCharArray();
  char[] c2 = s2.toCharArray();

  Arrays.sort(c1);
  Arrays.sort(c2);

  for(int i = 0; i < c1.length; i++) {
    if(c1[i] != c2[i]) return false;
  }

  return true;
}
durron597
  • 30,764
  • 16
  • 92
  • 150
  • 3
    +1 If you are going to check the length, I would do it before calling toCharArray. – Peter Lawrey Dec 03 '12 at 21:48
  • The `for` loop here can be replaced with `return Arrays.equals(c1, c2);`. https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#equals-char:A-char:A- – kaya3 Jan 21 '20 at 18:57
4

There is a various possible solution of determining if a string is Anagram or not. 1. using Array.sort() predefined method

String string1 = "abc";
String string2 = "bca";
char[] chars = string1.toCharArray();
char[] chars2 = string2.toCharArray();
Arrays.sort(chars);
Arrays.sort(chars2);
string1 = new String(chars);
string2 = new String(chars2);
if (string1.equalsIgnoreCase(string2)) {
  System.out.println("Anagram");
} else {
  System.out.println("Not Anagram");
}

Time complexity: Ω(n log n) 2. By Iterative method

char [] charArray = str.toCharArray();
if(str.length() == str1.length()){
    for(char ch : charArray){
        if(str1.indexOf(ch) == -1){
            System.out.println("Not Anagram");
        } 
    }    
    System.out.println("Anagram");
} else {
    System.out.println("Not Anagram");
}

Time complexity: Ω(n)

Though, the first algorithm is more readable second algorithm really executes faster.

Ram Bhandari
  • 469
  • 1
  • 4
  • 18
  • 1
    If you want to test for anagrams in a case-insensitive way, you should convert both strings to lowercase (or uppercase) before sorting. Otherwise `{'Z', 'a'}` and `{'A', 'z'}` are both in sorted order and the strings won't be equal ignoring case. The second "iterative" algorithm isn't correct for the strings `"aab"` and `"abb"`. – kaya3 Jan 21 '20 at 19:01
  • you can also add a break statement inside of index check if statement to make it more efficient – Reejesh PK Oct 15 '20 at 11:08
3

The reason it doesn't work:

Using "des" and "sed" as an example.

In the last iteration for which it matches, it will evaluate:

if(s1.charAt(i)==s2.charAt(j))
{
    delStr=s1.substring(i,i+1);
    newStr=s2.replace(delStr,"");
}

Which will be: if( "s" == "s" )

It will then enter the if block, and evaluate

newStr = "sed".replace("s","");

which will give you "ed", instead of an empty string.

The moral of the story is that you are always replacing characters from s2 less one character, which will never be empty.

Using String.replace() is bad anyway, because it will replace all instances of the character by default. With String.replace(), it would consider "sed" to be an anagram of "seeeeeeed". You would do better to use String.replaceFirst().

In any case, a starting point is to make the following modifications:

String newStr = s2;
...
// inside if block
newStr = newStr.replaceFirst( delStr, "" );
cmonkey
  • 4,076
  • 21
  • 43
2
import java.util.Scanner;

public class Anagrams {

static boolean isAnagram(String a, String b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    if (a.length() != b.length()) {
        return false;
    }

    char[] chars = a.toCharArray();
    for (char c : chars) {
        int index = b.indexOf(c);
        if (index != -1) {
            b = b.substring(0, index) + b.substring(index + 1, b.length());
        } else {
            return false;
        }
    }
    return b.isEmpty();
}

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    String a = scan.next();
    String b = scan.next();
    scan.close();
    boolean ret = isAnagram(a, b);
    System.out.println((ret) ? "Anagrams" : "Not Anagrams");

    }
}
Unheilig
  • 15,690
  • 193
  • 65
  • 96
isurie
  • 51
  • 1
  • 4
1

Below is a concise code snippet that determines whether two strings are anagrams in a single iteration of both strings, plus a final iteration of a 256 element array. This approach avoids sorting the characters in the strings and converting to/from Strings/char arrays by recording character counts in a mapping array.

static boolean isAnagram(String s1, String s2) {
    if (s1.length() != s2.length()) return false;
    int n = s1.length();
    int[] charMap = new int[256];
    for (int i = 0; i < n; i++) {
        char c1 = s1.charAt(i);
        charMap[c1]++;
        char c2 = s2.charAt(i);
        charMap[c2]--;
    }
    for (int i = 0; i < charMap.length; i++) {
        if (charMap[i] != 0) return false;
    }
    return true;
}

This code basically increments and decrements an index location in an array corresponding to a character. If any of the array elements are non-zero at the end of the iteration, there were an unequal amount of increments and decrements, and therefore the strings contain differing characters and cannot be anagrams of each other.

Given that this algorithm iterates the two same sized strings once, runtime is O(n). Space complexity is O(1) as the charMap is always constant depending on charset requirements.

broadbear
  • 544
  • 5
  • 18
1

This is a Java implementation that I wrote for using an array instead of a HashMap. This saves space, plus arrays are really fast.

public static boolean anagram(String s, String t) { 
        if (s.length() != t.length()) return false;

        int[] arr = new int[123];
        for (char c : s.toCharArray())
            arr[c]++;
        for (char c : t.toCharArray())
            arr[c]--;
        for (int i : arr)
            if (i != 0)
                return false;
        return true;
    }
Jing Ma
  • 119
  • 2
  • 10
1
public boolean checkAnagram(String s, String t) {
    s = s.toLowerCase();
    t = t.toLowerCase();

    // We can ignore blanks
    char[] word1 = s.replaceAll("\\s","").toCharArray();
    char[] word2 = t.replaceAll("\\s","").toCharArray();

    // Anagrams length should be the same
    if (word1.length != word2.length) {
        return false;
    }

    // Sorting arrays is pretty fast, it can be O(logn) 
    Arrays.sort(word1);
    Arrays.sort(word2);

    if (Arrays.equals(word1, word2)) {
        return true;
    }

    return false;
}
pgardunoc
  • 173
  • 1
  • 6
1
Using HashMap
public boolean isAnagram(String word, String anagram) {
    if (word.length() != anagram.length())
        return false;

    int count = 0;
    Map<Character, Integer> map = new HashMap<>();

    for (int i = 0; i < word.length(); i++) {
        if (!map.containsKey(word.charAt(i)))
            map.put(word.charAt(i), 1);
        else
            map.put(word.charAt(i), map.get(word.charAt(i)) + 1);
    }

    for (int i = 0; i < anagram.length(); i++) {
        if (!map.containsKey(anagram.charAt(i)))
            return false;
        else if (map.get(anagram.charAt(i)) >= 1)
            map.put(anagram.charAt(i), map.get(anagram.charAt(i)) - 1);
        else
            return false;
    }

    return true;
}
0

just making sure, you are trying to check to see if s1 is a anagram of s2 correct? That would also mean s2 is a an anagram of s1. So i would just sort s1 and s2 and check to see if they are equal.

String string1 = "fdafdas";
String string2 = "fdwqkjl";
char[] chars = string1.toCharArray();
char[] chars2 = string2.toCharArray();
Arrays.sort(chars);
Arrays.sort(chars2);
string1 = new String(chars);
string2 = new String(chars2);
if (string1.equals(string2)) {
    //They are an anagram
}
user1103205
  • 165
  • 2
  • 13
0
public boolean isAnagram(String a, String b) {

  boolean result = false;

  final String one = a.replaceAll("[\\s+\\W+]", "").toLowerCase();

  final String two = b.replaceAll("[\\s+\\W+]", "").toLowerCase();

  if (one.length() == two.length()) {

      final char[] oneArray =  one.toCharArray();

      final char[] twoArray =  two.toCharArray(); 

      Arrays.sort(oneArray);

      Arrays.sort(twoArray);

      result = Arrays.equals(oneArray, twoArray);

    }

  return result; 

}
0

I guess the following solution has O(n) complexity, let me know if someone differs.

import java.util.HashMap;
import java.util.Scanner;


public class Anagrams {

    static boolean isAnagram(String word1, String word2)
    {
        if(word1.length() != word2.length()) {
            return false;
        }
        int flag=0;
        HashMap<Character,Integer> table = new HashMap<Character,Integer>();
        for(int i=0; i< word1.length();i++) {
            table.put(word1.charAt(i),1);
        }

        for(int i=0; i< word2.length();i++) {
            if(table.containsKey(word2.charAt(i))) {
                continue;
            } else {
                flag=1;
                break;
            }   
        }
        return flag == 0;
    }

    public static void main(String[] args) {
        System.out.println("Enter your string");
        Scanner sc= new Scanner(System.in);
        String word1= sc.nextLine();
        String word2=sc.nextLine();

         boolean result = isAnagram(word1,word2);
         if(result) {
             System.out.println("The words are Anagrams");
         } else{
             System.out.println("The words are not Anagrams");   
         }
    }
}
xenteros
  • 14,275
  • 12
  • 47
  • 81
0

O(n) solution without any kind of sorting and using only one map. Also added proper null check missing in other solutions.

public boolean isAnagram(String leftString, String rightString) {
  if (leftString == null || rightString == null) {
    return false;
  } else if (leftString.length() != rightString.length()) {
    return false;
  }

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

  for(int i = 0; i < leftString.length(); i++){
    char charFromLeft = leftString.charAt(i);
    int nrOfCharsInLeft = occurrencesMap.containsKey(charFromLeft) ? occurrencesMap.get(charFromLeft) : 0;
    occurrencesMap.put(charFromLeft, ++nrOfCharsInLeft);
    char charFromRight = rightString.charAt(i);
    int nrOfCharsInRight = occurrencesMap.containsKey(charFromRight) ? occurrencesMap.get(charFromRight) : 0;
    occurrencesMap.put(charFromRight, --nrOfCharsInRight);
  }

  for(int occurrencesNr : occurrencesMap.values()){
    if(occurrencesNr != 0){
      return false;
    }
  }

  return true;
}

and less generic solution but a little bit faster one:

public boolean isAnagram(String leftString, String rightString) {
  if (leftString == null || rightString == null) {
    return false;
  } else if (leftString.length() != rightString.length()) {
    return false;
  }

  char letters[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
  Map<Character, Integer> occurrencesMap = new HashMap<>();
  for (char l : letters) {
    occurrencesMap.put(l, 0);
  }

  for(int i = 0; i < leftString.length(); i++){
    char charFromLeft = leftString.charAt(i);
    Integer nrOfCharsInLeft = occurrencesMap.get(charFromLeft);
    occurrencesMap.put(charFromLeft, ++nrOfCharsInLeft);
    char charFromRight = rightString.charAt(i);
    Integer nrOfCharsInRight = occurrencesMap.get(charFromRight);
    occurrencesMap.put(charFromRight, --nrOfCharsInRight);
  }

  for(Integer occurrencesNr : occurrencesMap.values()){
    if(occurrencesNr != 0){
      return false;
    }
  }

  return true;
}
goroncy
  • 1,989
  • 17
  • 16
0

Here's a Simpler approach relying mostly on java The complete code is here https://github.com/rdsr/algorithms/blob/master/src/jvm/misc/AnagramsList.java (Note this solves a related by different problem)

class Anagram {
    Map<Character, Integer> anagram;

    Anagram(String s) {
        anagram = new HashMap<Character, Integer>();

        for (final Character c : s.toCharArray()) {
            if (anagram.containsKey(c)) {
                anagram.put(c, 1 + anagram.get(c));
            } else {
                anagram.put(c, 1);
            }
        }
    }

    @Override
    public int hashCode() {
        //.. elided
    }

    @Override
    public boolean equals(Object obj) {
        //.. elided
    }
}


    public class Anagrams {
            public static void main(String[] args) {
                System.out.println(new Anagram("abc").equals(new Anagram("bac")));
            }
        }
RD.
  • 290
  • 4
  • 12
  • One suggestion. you can get anagram.get(c) and check null instead of containsKey ( you are iterating two times just to check ) – Mani Apr 12 '14 at 13:19
0

Faster version using bit vector approach for anagram substrings

public boolean isAnagram(String _source1, String _source2)
{

    int flag = 0, char_index = 0, counter = 0;
    if(_source2.length() < _source1.length()){
        return false;
    }
    char[] _stringchar = _source1.toCharArray();
    char[] _tocheck = _source2.toCharArray();
    for(char character : _stringchar)
    {
        char_index = character - 'a';
        if((flag & (1 << char_index)) == 0)
            flag |= (1 << char_index);
    }

    for(char toCheckcChar : _tocheck)
    {
        char_index = toCheckcChar - 'a';

        if((flag & (1 << char_index)) > 0)
            counter++;
        else
            counter = 0;

        if(counter == _source1.length())
            return true;

    }

    return false;
}
Roshan
  • 511
  • 4
  • 15
0

The simple reason is, because replace function creates a new String object. It does not do anything to the actual string (in your case s2), because in Java, strings are final by nature. So as pointed out by cmonkey, you are always removing one character from your string s2, but in reality a new String object is created with 1 character less, s2 remains as is.

The simple way to get this working in your case would be to create a new string object and assign it to yourself.

{
    s2=s2.replace(delString,"");
    ....
    if(s2.empty()) return true;
    return false;
}
Artjom B.
  • 58,311
  • 24
  • 111
  • 196
Bhavya
  • 43
  • 6
0

once i made a test for job interview about anagrams. I uploaded it to my github account. The java code checks if a text file (with multiple lines) is an anagram poem or anagram text.

https://github.com/javocsoft/anagram_poem_checker

Hope it helps!

Bye.

JavocSoft
  • 206
  • 2
  • 6
0

just see at line newStr=s2.replace(delStr,"");

what you are doing here replacing a char in s2 and assigning back to newStr, means you are not changing anything in s2. Just replace this code by below one it will work fine

newStr=newStr.replace(delStr,"");

RKP
  • 89
  • 6
0

I took some time out to actually pen down the logic and write a code to check for two strings, if they are anagrams or not. Of course with the help of the above answers! XD

public static void main(String[] args) {

    Map<Character, Integer> char_map = new HashMap<Character, Integer>();
    Map<Character, Integer> empty_map = new HashMap<Character, Integer>();
    String a = "HelloP";
    String b = "HePlol";

    if (a.length() != b.length()) {
        System.out.println("false");
        System.exit(0);
    }

    for (char c : a.toLowerCase().toCharArray()) {
        empty_map.put(c, 0);
        if (char_map.containsKey(c))
            char_map.put(c, 1 + char_map.get(c));
        else
            char_map.put(c, 1);
    }

    for (char c : b.toLowerCase().toCharArray())
        if (char_map.containsKey(c))
            char_map.put(c, char_map.get(c) - 1);

    System.out.println(char_map.equals(empty_map));
}
indieNik
  • 134
  • 2
  • 12
  • (I don't quite like the name `empty_map`.) You can use `old = char_map.put(c, 1); if (null != old) char_map.put(c, old + 1)` for one lookup less per character. – greybeard Dec 10 '15 at 07:11
0

I think this works with complexity O(2n)

public static boolean isAnagram(String str1, String str2){
    if(str1.length() != str2.length()){ return false;}
    int[] buffer = new int[256];
    for(char ch : str1.toCharArray()){
        buffer[ch]++;
    }
    for(char ch : str2.toCharArray()){
        if(buffer[ch]==0) return false;
        buffer[ch] = (buffer[ch] > 0)?(buffer[ch] - 1 ): -1 ;   
    }
    return true;
}
0
import java.util.Scanner;

public class JavaProgram
{
    public static void main(String[] input)
    {
        String str1, str2;
        int len, len1, len2, i, j, found=0, not_found=0;
        Scanner scan = new Scanner(System.in);

        System.out.print("Enter First String : ");
        str1 = scan.nextLine();
        System.out.print("Enter Second String : ");
        str2 = scan.nextLine();

        len1 = str1.length();
        len2 = str2.length();

        if(len1 == len2)
        {
            len = len1;
            for(i=0; i<len; i++)
            {
                found = 0;
                for(j=0; j<len; j++)
                {
                    if(str1.charAt(i) == str2.charAt(j))
                    {
                        found = 1;
                        break;
                    }
                }
                if(found == 0)
                {
                    not_found = 1;
                    break;
                }
            }
            if(not_found == 1)
            {
                System.out.print("Strings are not Anagram to Each Other..!!");
            }
            else
            {
                System.out.print("Strings are Anagram");
            }
        }
        else
        {
            System.out.print("Both Strings Must have the same number of Character to be an Anagram");
        }
    }
}
0
public class Anagram {
    public boolean isAnagram(
            String left, 
            String right) {
        if (left.length() == right.length()) {
            Map<Character, Integer> map = new HashMap<>();
            char[] a = left.toCharArray(), b = right.toCharArray();
            for (int i = 0; i < a.length; i++) {
                accumulate(map, a[i]);
                accumulate(map, b[i]);
            }
            for (char c : map.keySet()) {
                if (map.get(c) > 0) {
                    return false;
                }
            }
            return true;
        } else {
            return false;
        }
    }

    private void accumulate(
            Map<Character, Integer> map, 
            char key) {
        if (map.containsKey(key)) {
            map.put(key, Math.abs(map.get(key) - 1));
        } else {
            map.put(key, 1);
        }
    }
}
0

Here is my solution from your aspect

private static boolean isAnagram(String s1, String s2){
    int count = 0;
    boolean flag = false;

    if(s1.length() != s2.length()){
        return false;
    }
    //checks whether both word's letters are the same
    for (int i = 0; i < s1.length(); i++){
        for (int j = 0; j < s2.length(); j++){
            if(s1.charAt(i) == s2.charAt(j)){
                count++;
                break;
            }
        }
    }
    //if count equals to one of the Strings length then it is an anagram
    if(count == s2.length() ){
        flag = true;
    }
    return flag;
}
0
    String str1="Mother In Law";
    String str2="Hitler Woman";
    char[] anag1=str1.replaceAll("\\s", "").toLowerCase().toCharArray();
    char[] anag2=str2.replaceAll("\\s", "").toLowerCase().toCharArray();
    Arrays.sort(anag1);
    Arrays.sort(anag2);
    System.out.println(Arrays.equals(anag1, anag2)? "words are anagrams":"words are not anagrams");
0
public static boolean isAnagram(String s1, String s2) {
    boolean aux = true;
    if (s1.length() != s2.length()){
        aux = false;
    }else{ 
        for (int i = 0; i < s1.length(); i++)
            if(s2.toUpperCase().indexOf(s1.toUpperCase().substring(i, i+1)) == -1) aux = false;
    }
    return aux;
}
serge
  • 11
  • 4
0
public class SampleAnagram {

    public static void main(String ...s) {


        String s1 = "work";
        String s2="kwro";

        System.out.println(s1.charAt(0));

        int s1L = s1.length();
        int s2L = s2.length();

        int totalCount = 0;

            for(int i=0;i<s1L;i++) {

                for(int j=0;j<s2L;j++) {

                if(s1.charAt(i)==(s2.charAt(j))) {

                    totalCount = totalCount+1;
                }
            }
        }

            System.out.println(totalCount);


            if(s1.length()==totalCount && s2.length()==totalCount) {

                System.out.println("given the input as anagram");
            }

    }



}
halfelf
  • 8,484
  • 13
  • 47
  • 58
Dharma
  • 31
  • 2
0

Here is another suggestion without initialising an int[256] but an int[26] for English alphabet.

public static void main(String[] args) {
    System.out.println(isAnagram("restful", "fluster"));
}

static boolean isAnagram(String s1, String s2) {
    if (s1.length() != s2.length()) {
        return false;
    }
    int[] countArray = new int[26];
    for (int i = 0; i < s1.length(); i++) {
        countArray[getIndex(i, s1)]++;
        countArray[getIndex(i, s2)]--;
    }
    for (int i = 0; i < countArray.length; i++) {
        if (countArray[i] != 0) {
            return false;
        }
    }
    return true;
}

public static int getIndex(int position, String value) {
    return value.charAt(position) - 'a';
}

Best George Tsopouridis

0
public static boolean isAnagram(String s1, String s2) {
    if (s1.length() != s2.length()) {
        return false;
    }
    Map<Character, Integer> frequencies = new HashMap<>();
    for (int i = 0; i < s1.length(); i++) {
        if (frequencies.containsKey(s1.charAt(i))) {
            frequencies.put(s1.charAt(i), frequencies.get(s1.charAt(i)) + 1);
        } else {
            frequencies.put(s1.charAt(i), 1);
        }
    }
    for (int i = 0; i < s2.length(); i++) {
        if (frequencies.containsKey(s2.charAt(i))) {
            int frequency = frequencies.get(s2.charAt(i));
            if (--frequency == 0) {
                frequencies.remove(s2.charAt(i));
            } else {
                frequencies.put(s2.charAt(i), frequencies.get(s2.charAt(i)) - 1);
            }
        }
    }
    return frequencies.isEmpty();
}
Ihor M.
  • 1,831
  • 1
  • 27
  • 51
0
  1. Compare lengths of both strings if equal
  2. Convert both strings to lowercase so you can compare efficiently
  3. Loop to check if String1 contains a character in String2.
  4. Set a counter to the length of one of the strings and decrease -1 when there's a match

    public boolean isAnagram(String s1, String s2) {
    
    if(s1.length() != s2.length()) {
        return false;
    }
    
    int counter= s1.length();
    s1 = s1.toLowerCase();
    s2= s2.toLowerCase();
    
    for (int i=0; i<s1.length();i++ ) {
    
            if (s2.contains(s1.charAt(i)+"")) {
    
                counter--;              
        }
    }
    
    if (counter<=0) {
    
        return true;
    }
    return false;
    }
    
karto
  • 3,163
  • 8
  • 40
  • 63
0

Using the Java streams this can be simplified in just 5 lines of code (https://github.com/vspiliop/java-puzzles/blob/master/src/gy/etiolo/puzzles/streams/Anagrams.java):

/**
 * Are two strings anagrams.
 */
public class Anagrams {
  public static void main(String ... args) {
    String word1 = "abcdefg";
    String word2 = "gfedabc";

    System.out.println("Are they anagrams: " + isAnagram(word1, word2));
  }

  private static boolean isAnagram(String word1, String word2) {
    int [] mask = new int[26];
    Arrays.fill(mask, 0);
    word1.toLowerCase().chars().forEach(c -> mask['z' - c]++);
    word2.toLowerCase().chars().forEach(c -> mask['z' - c]--);
    return Arrays.stream(mask).sum() == 0;
  }
}

Check ascii table here: http://www.asciitable.com/

Vassilis
  • 666
  • 5
  • 17
-1
import java.util.*;
class Anagrams 
{
    public static void main(String[] args) 
    {
        System.out.println("Enter the two words");
        Scanner scan = new Scanner(System.in);
        String word1 = scan.next();
        String word2=scan.next();

        StringBuilder sb1= new StringBuilder(word1);
        StringBuilder sb2= new StringBuilder(word2);
        int count=0;
        System.out.println("length ! "+sb1.length());
        System.out.println("Length ! "+sb2.length());
        if(sb1.length()==sb2.length()){
            for(int i=0;i<sb1.length();i++){
                for(int k=0;k<sb2.length();k++){
                    if(sb1.charAt(i)==sb2.charAt(k)){
                        sb2.deleteCharAt(k);
                        count++;
                        System.out.println("Count is "+count);
                        break;
                    }
                }
            }

            if(count==sb1.length()){

                System.out.println("Anagrams!");
            }
            else{
                System.out.println("Not Anagrams");
            }
        }
        else{
            System.out.println("Not equal in length");
        }
    }
}
Kundan Jha
  • 54
  • 8
-1
public static void arrang(String s, String str){

  char a[] = new char[s.length()];
  char b[] = new char[str.length()];
  int arr1[] = new int[s.length()];
  int arr2[] = new int[str.length()];

  if( a.length == b.length ) {
    System.out.println("two numbers can't be anagrams");
    return;
  }

  for( int i = 0 ; i < str.length() ; i++ ) {
    a[i] = s.toLowerCase().charAt(i);
    b[i] = str.toLowerCase().charAt(i);
  }

  // casting
  for( int i = 0 ; i < s.length() ; i++ ) {
    arr1[i]=(int)a[i];
    arr2[i]=(int)b[i];
  }

  for( int i = 0 ; i < s.length() ; i++ ) {
    for( int j = 1 ; j < s.length() ; j++ ) {
      if( arr1[j-1] > arr1[j] ) {
        int temp = arr1[j];
        arr1[j] = arr1[j-1];
        arr1[j-1] = temp;
      }
    }
  }

  for( int i = 0 ; i < s.length() ; i++ ) {
    for( int j = 1 ; j < s.length() ; j++ ) {
      if( arr2[j-1] > arr2[j] ) {
        int temp = arr2[j];
        arr2[j] = arr2[j-1];
        arr2[j-1] = temp;
      }
    }
  }

  for( int i = 0 ; i < s.length() ; i++ ) {
    a[i] = (char)arr1[i];
    b[i] = (char)arr2[i];
  }

  int count = 0;
  for( int i = 0 ; i < s.length() ; i++ ) {
    if( a[i] == b[i] ) {
      count++;
    }
  }
  if( count == s.length() ) {
    System.out.println("two strings are anagrams");
  }
  else{
    System.out.println("not anagrams");
  }
}
x00
  • 11,008
  • 2
  • 10
  • 34