найти, если два слова являются анаграммами друг друга - PullRequest
23 голосов
/ 21 ноября 2010

Я ищу метод, чтобы определить, являются ли две строки анаграммами друг друга.

Ex: string1 - abcde
string2 - abced
Ans = true
Ex: string1 - abcde
string2 - abcfed
Ans = false

Решение, которое я придумал, заключается в сортировке обеих строк и сравнении каждого символа из обеих строкдо конца любой строки. Это будет O (logn). Я ищу другой эффективный метод, который не изменяет сравниваемые 2 строки

Ответы [ 22 ]

52 голосов
/ 21 ноября 2010

Подсчитайте частоту каждого символа в двух строках. Проверьте, совпадают ли две гистограммы. O (n) время, O (1) пространство (при условии ASCII) (Конечно, это еще O (1) пространство для Unicode, но таблица станет очень большой).

32 голосов
/ 21 ноября 2010

Получить таблицу простых чисел, достаточную для сопоставления каждого простого числа с каждым символом. Итак, начните с 1, проходя через строку, умножьте число на простое число, представляющее текущий символ. Число, которое вы получите, зависит только от символов в строке, но не от их порядка, и каждый уникальный набор символов соответствует уникальному номеру, поскольку любое число может быть разложено только одним способом. Таким образом, вы можете просто сравнить два числа, чтобы сказать, являются ли строки анаграммами друг друга.

К сожалению, для этого нужно использовать целочисленную арифметику с множественной точностью (произвольной точности), иначе вы получите исключения переполнения или округления при использовании этого метода.
Для этого вы можете использовать библиотеки типа BigInteger, GMP, MPIR или IntX.

псевдокод:

prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101}

primehash(string)
    Y = 1;
    foreach character in string
        Y = Y * prime[character-'a']

    return Y

isanagram(str1, str2)
    return primehash(str1)==primehash(str2)
23 голосов
/ 21 ноября 2010
  1. Создать Hashmap, где ключ - буква и значение - частота буквы,
  2. для первой строки заполнить хэш-карту (O (n))
  3. для счетчика уменьшений второй строки и удаления элемента из хэш-карты O (n)
  4. если hashmap пуст, строка является анаграммой, иначе нет.
8 голосов
/ 30 сентября 2012

Шаги:

  1. проверить длину обоих слов / строк, если они равны, тогда только приступить к проверке анаграммы, иначе ничего не делать
  2. отсортировать оба слова / строки, а затем сравнить

JAVA КОД ТО ЖЕ ВРЕМЯ:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package anagram;

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

/**
 *
 * @author Sunshine
 */
public class Anagram {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        // TODO code application logic here
        System.out.println("Enter the first string");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s1 = br.readLine().toLowerCase();
        System.out.println("Enter the Second string");
        BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in));
        String s2 = br2.readLine().toLowerCase();
        char c1[] = null;
        char c2[] = null;
        if (s1.length() == s2.length()) {


            c1 = s1.toCharArray();
            c2 = s2.toCharArray();

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

            if (Arrays.equals(c1, c2)) {
                System.out.println("Both strings are equal and hence they have anagram");
            } else {
                System.out.println("Sorry No anagram in the strings entred");
            }

        } else {
            System.out.println("Sorry the string do not have anagram");
        }
    }
}
3 голосов
/ 09 декабря 2012

C #

public static bool AreAnagrams(string s1, string s2)
{
  if (s1 == null) throw new ArgumentNullException("s1");
  if (s2 == null) throw new ArgumentNullException("s2");

  var chars = new Dictionary<char, int>();
  foreach (char c in s1)
  {
      if (!chars.ContainsKey(c))
          chars[c] = 0;
      chars[c]++;
  }
  foreach (char c in s2)
  {
      if (!chars.ContainsKey(c))
          return false;
      chars[c]--;
  }

  return chars.Values.All(i => i == 0);
}

Некоторые тесты:

[TestMethod]
public void TestAnagrams()
{
  Assert.IsTrue(StringUtil.AreAnagrams("anagramm", "nagaramm"));
  Assert.IsTrue(StringUtil.AreAnagrams("anzagramm", "nagarzamm"));
  Assert.IsTrue(StringUtil.AreAnagrams("anz121agramm", "nag12arz1amm"));
  Assert.IsFalse(StringUtil.AreAnagrams("anagram", "nagaramm"));
  Assert.IsFalse(StringUtil.AreAnagrams("nzagramm", "nagarzamm"));
  Assert.IsFalse(StringUtil.AreAnagrams("anzagramm", "nag12arz1amm"));
}
2 голосов
/ 21 апреля 2014

Код для определения того, являются ли два слова анаграммами:

Логика объясняется уже в нескольких ответах и ​​лишь немногие просят код.Это решение создает результат за O (n).

Этот подход подсчитывает количество вхождений каждого символа и сохраняет его в соответствующем ASCII-местоположении для каждой строки.А затем сравните два массива.Если она не равна, данные строки не являются анаграммами.

public boolean isAnagram(String str1, String str2)
{
    //To get the no of occurrences of each character and store it in their ASCII location
    int[] strCountArr1=getASCIICountArr(str1);
    int[] strCountArr2=getASCIICountArr(str2);

    //To Test whether the two arrays have the same count of characters. Array size 256 since ASCII 256 unique values
    for(int i=0;i<256;i++)
    {
        if(strCountArr1[i]!=strCountArr2[i])
            return false;
    }
    return true;
}

public int[] getASCIICountArr(String str)
{
    char c;
    //Array size 256 for ASCII
    int[] strCountArr=new int[256];
    for(int i=0;i<str.length();i++)
    {
        c=str.charAt(i); 
        c=Character.toUpperCase(c);// If both the cases are considered to be the same
        strCountArr[(int)c]++; //To increment the count in the character's ASCII location
    }
    return strCountArr;
}
2 голосов
/ 22 апреля 2014

Использование хэш-карты ASCII, которая позволяет искать O (1) для каждого символа.

Приведенный выше пример java конвертируется в нижний регистр, который кажется неполным.У меня есть пример на C, который просто инициализирует массив хэш-карты для ASCII-значений до '-1'

Если строка2 отличается по длине от строки 1, анаграммы отсутствуют

Иначе, мы обновляем соответствующие значения хэш-карты до 0 для каждого символа в строке1 и строке2

Затем для каждого символа в строке1 мы обновляем счетчик в карте хеш-кода.Аналогично, мы уменьшаем значение счетчика для каждого символа в строке 2.

В результате должны быть установлены значения 0 для каждого символа, если они являются анаграммами.если нет, некоторое положительное значение, установленное string1, остается

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ARRAYMAX 128

#define True        1
#define False       0

int isAnagram(const char *string1, 
            const char *string2) {

    int str1len = strlen(string1);
    int str2len = strlen(string2);

    if (str1len != str2len) /* Simple string length test */
        return False;

    int * ascii_hashtbl = (int * ) malloc((sizeof(int) * ARRAYMAX));
    if (ascii_hashtbl == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        return -1;
    }
    memset((void *)ascii_hashtbl, -1, sizeof(int) * ARRAYMAX);
    int index = 0;
    while (index < str1len) { /* Populate hash_table for each ASCII value 
                                in string1*/
        ascii_hashtbl[(int)string1[index]] = 0;
        ascii_hashtbl[(int)string2[index]] = 0;
        index++;
    }
    index = index - 1;
    while (index >= 0) {
        ascii_hashtbl[(int)string1[index]]++; /* Increment something */
        ascii_hashtbl[(int)string2[index]]--; /* Decrement something */
        index--;
    }
    /* Use hash_table to compare string2 */
    index = 0;
    while (index < str1len) {
        if (ascii_hashtbl[(int)string1[index]] != 0) {
            /* some char is missing in string2 from string1 */
            free(ascii_hashtbl);
            ascii_hashtbl = NULL;
            return False;
        }
        index++;
    }
    free(ascii_hashtbl);
    ascii_hashtbl = NULL;
    return True;
}

int main () {
    char array1[ARRAYMAX], array2[ARRAYMAX];
    int flag;

    printf("Enter the string\n");
    fgets(array1, ARRAYMAX, stdin);
    printf("Enter another string\n");
    fgets(array2, ARRAYMAX, stdin);

    array1[strcspn(array1, "\r\n")] = 0;
    array2[strcspn(array2, "\r\n")] = 0;
    flag = isAnagram(array1, array2);
    if (flag == 1)
        printf("%s and %s are anagrams.\n", array1, array2);
    else if (flag == 0)
        printf("%s and %s are not anagrams.\n", array1, array2);

    return 0;
}
1 голос
/ 18 ноября 2012

Как насчет Xor'ing обеих струн ???Это определенно будет O (n)

char* arr1="ab cde";
int n1=strlen(arr1);
char* arr2="edcb a";
int n2=strlen(arr2);
// to check for anagram;
int c=0;
int i=0, j=0;   
if(n1!=n2) 
  printf("\nNot anagram");
else {
   while(i<n1 || j<n2)
   {
       c^= ((int)arr1[i] ^ (int)arr2[j]);
       i++;
       j++;
   }
}

if(c==0) {
    printf("\nAnagram");
}
else printf("\nNot anagram");

}

1 голос
/ 30 апреля 2011

Как насчет этого?

a = "lai d"
b = "di al"
sorteda = []
sortedb = []
for i in a:
    if i != " ":
        sorteda.append(i)
        if c == len(b):
            for x in b:
                c -= 1
                if x != " ":
                    sortedb.append(x)
sorteda.sort(key = str.lower)
sortedb.sort(key = str.lower)

print sortedb
print sorteda

print sortedb == sorteda
1 голос
/ 30 марта 2018

давайте возьмем вопрос: учитывая две строки s и t, напишите функцию, чтобы определить, является ли t анаграммой s.

Например, s = "анаграмма", t = "нагарам", верните истину. s = "крыса", t = "машина", возврат false.

Метод 1 (с использованием HashMap):

public class Method1 {

    public static void main(String[] args) {
        String a = "protijayi";
        String b = "jayiproti";
        System.out.println(isAnagram(a, b ));// output => true

    }

    private static boolean isAnagram(String a, String b) {
        Map<Character ,Integer> map = new HashMap<>();
        for( char c : a.toCharArray()) {
            map.put(c,    map.getOrDefault(c, 0 ) + 1 );
        }
        for(char c : b.toCharArray()) {
            int count = map.getOrDefault(c, 0);
            if(count  == 0 ) {return false ; }
            else {map.put(c, count - 1 ) ; }
        }

        return true;
    }

}

Метод 2:

public class Method2 {
public static void main(String[] args) {
    String a = "protijayi";
    String b = "jayiproti";


    System.out.println(isAnagram(a, b));// output=> true
}

private static boolean isAnagram(String a, String b) {


    int[] alphabet = new int[26];
    for(int i = 0 ; i < a.length() ;i++) {
         alphabet[a.charAt(i) - 'a']++ ;
    }
    for (int i = 0; i < b.length(); i++) {
         alphabet[b.charAt(i) - 'a']-- ;
    }

    for(  int w :  alphabet ) {
         if(w != 0 ) {return false;}
    }
    return true;

}
}

Метод 3:

public class Method3 {
public static void main(String[] args) {
    String a = "protijayi";
    String b = "jayiproti";


    System.out.println(isAnagram(a, b ));// output => true
}

private static boolean isAnagram(String a, String b) {
    char[] ca = a.toCharArray() ;
    char[] cb = b.toCharArray();
    Arrays.sort(   ca     );

    Arrays.sort(   cb        );
    return Arrays.equals(ca , cb );
}
}

Метод 4:

public class AnagramsOrNot {
    public static void main(String[] args) {
        String a = "Protijayi";
        String b = "jayiProti";
        isAnagram(a, b);
    }

    private static void isAnagram(String a, String b) {
        Map<Integer, Integer> map = new LinkedHashMap<>();

        a.codePoints().forEach(code -> map.put(code, map.getOrDefault(code, 0) + 1));
        System.out.println(map);
        b.codePoints().forEach(code -> map.put(code, map.getOrDefault(code, 0) - 1));
        System.out.println(map);
        if (map.values().contains(0)) {
            System.out.println("Anagrams");
        } else {
            System.out.println("Not Anagrams");
        }
    }
}

В Python:

def areAnagram(a, b):
    if len(a) != len(b): return False
    count1 = [0] * 256
    count2 = [0] * 256
    for i in a:count1[ord(i)] += 1
    for i in b:count2[ord(i)] += 1

    for i in range(256):
        if(count1[i] != count2[i]):return False    

    return True


str1 = "Giniiii"
str2 = "Protijayi"
print(areAnagram(str1, str2))

Давайте рассмотрим еще один известный вопрос для интервью: сгруппируйте анаграммы по заданной строке:

public class GroupAnagrams {
    public static void main(String[] args) {
        String a = "Gini Gina Protijayi iGin aGin jayiProti Soudipta";
        Map<String, List<String>> map = Arrays.stream(a.split(" ")).collect(Collectors.groupingBy(GroupAnagrams::sortedString));
        System.out.println("MAP => " + map);
        map.forEach((k,v) -> System.out.println(k +" and the anagrams are =>" + v ));
        /*
         Look at the Map output:
        MAP => {Giin=[Gini, iGin], Paiijorty=[Protijayi, jayiProti], Sadioptu=[Soudipta], Gain=[Gina, aGin]}
        As we can see, there are multiple Lists. Hence, we have to use a flatMap(List::stream)
        Now, Look at the output:
        Paiijorty and the anagrams are =>[Protijayi, jayiProti]

        Now, look at this output:
        Sadioptu and the anagrams are =>[Soudipta]
        List contains only word. No anagrams.
        That means we have to work with map.values(). List contains all the anagrams.


        */
        String stringFromMapHavingListofLists = map.values().stream().flatMap(List::stream).collect(Collectors.joining(" "));
        System.out.println(stringFromMapHavingListofLists);
    }

    public static String sortedString(String a) {
        String sortedString = a.chars().sorted()
                .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();

        return sortedString;

    }

    /*
     * The output : Gini iGin Protijayi jayiProti Soudipta Gina aGin
     * All the anagrams are side by side.
     */
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...