I am looking for a method to find if two strings are anagrams of one another.
我正在寻找一种方法,来查找两个字符串是否是彼此的字谜。
Ex: string1 - abcde
string2 - abced
Ans = true
Ex: string1 - abcde
string2 - abcfed
Ans = false
the solution i came up with so for is to sort both the strings and compare each character from both strings till the end of either strings.It would be O(logn).I am looking for some other efficient method which doesn't change the 2 strings being compared
我提出的解决方案是对字符串进行排序,并将两个字符串的每个字符进行比较,直到字符串的末尾。这将是O(logn)。我正在寻找其他一些有效的方法,它不会改变被比较的两个字符串。
22 个解决方案
#1
51
Count the frequency of each character in the two strings. Check if the two histograms match. O(n) time, O(1) space (assuming ASCII) (Of course it is still O(1) space for Unicode but the table will become very large).
计算两个字符串中每个字符的频率。检查两个直方图是否匹配。O(n)时间,O(1)空间(假设ASCII)(当然,它仍然是Unicode的空间,但表将变得非常大)。
#2
31
Get table of prime numbers, enough to map each prime to every character. So start from 1, going through line, multiply the number by the prime representing current character. Number you'll get is only depend on characters in string but not on their order, and every unique set of characters correspond to unique number, as any number may be factored in only one way. So you can just compare two numbers to say if a strings are anagrams of each other.
获取质数表,足够将每个质数映射到每个字符。所以从1开始,通过直线,将数字乘上代表当前字符的质数。你将得到的数字只取决于字符串中的字符,而不是它们的顺序,并且每一组独特的字符都对应于唯一的数字,因为任何数字都可能只被一个方法分解。所以你可以把两个数字比较一下,如果一个字符串是相互的。
Unfortunately you have to use multiple precision (arbitrary-precision) integer arithmetic to do this, or you will get overflow or rounding exceptions when using this method.
For this you may use libraries like BigInteger
, GMP
, MPIR
or IntX
.
不幸的是,您必须使用多个精度(任意精度)的整数算法来实现这一点,否则在使用此方法时将会出现溢出或舍入异常。为此,您可以使用像BigInteger、GMP、MPIR或IntX这样的库。
Pseudocode:
伪代码:
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)
#3
21
- Create a Hashmap where key - letter and value - frequencey of letter,
- 创建一个Hashmap,其中关键字和值-频率的字母,
- for first string populate the hashmap (O(n))
- 对于第一个字符串填充hashmap (O(n))
- for second string decrement count and remove element from hashmap O(n)
- 对于第二个字符串递减计数,并从hashmap O(n)中删除元素
- if hashmap is empty, the string is anagram otherwise not.
- 如果hashmap为空,则字符串为anagram。
#4
8
The steps are:
的步骤是:
- check the length of of both the words/strings if they are equal then only proceed to check for anagram else do nothing
- 检查单词/字符串的长度,如果它们是相等的,那么只需要检查另一个字母,否则什么也不做。
- sort both the words/strings and then compare
- 对单词/字符串进行排序,然后进行比较。
JAVA CODE TO THE SAME:
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");
}
}
}
#5
3
C#
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);
}
Some tests:
一些测试:
[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"));
}
#6
2
Code to find whether two words are anagrams:
代码查找两个单词是字谜:
Logic explained already in few answers and few asking for the code. This solution produce the result in O(n) time.
逻辑解释已经很少,很少有人问代码。这个解决方案在O(n)时间内产生结果。
This approach counts the no of occurrences of each character and store it in the respective ASCII location for each string. And then compare the two array counts. If it is not equal the given strings are not anagrams.
该方法计算每个字符的出现次数,并将其存储在每个字符串各自的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;
}
#7
2
Using an ASCII hash-map that allows O(1) look-up for each char.
使用允许O(1)查找每个字符的ASCII hashmap。
The java example listed above is converting to lower-case that seems incomplete. I have an example in C that simply initializes a hash-map array for ASCII values to '-1'
上面列出的java示例将转换为不完整的小写。我在C中有一个例子,它简单地将一个hashmap数组初始化为'-1'
If string2 is different in length than string 1, no anagrams
如果string2的长度与字符串1不同,则没有字谜。
Else, we update the appropriate hash-map values to 0 for each char in string1 and string2
另外,我们为string1和string2中的每个char更新适当的hashmap值为0。
Then for each char in string1, we update the count in hash-map. Similarily, we decrement the value of the count for each char in string2.
然后,对于string1中的每个char,我们更新hashmap中的count。类似地,我们递减string2中每个char的值。
The result should have values set to 0 for each char if they are anagrams. if not, some positive value set by string1 remains
如果它们是字谜,结果应该为每个char设置值为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;
}
#8
1
Well you can probably improve the best case and average case substantially just by checking the length first, then a quick checksum on the digits (not something complex, as that will probably be worse order than the sort, just a summation of ordinal values), then sort, then compare.
你可以通过先检查长度来改进最好的情况和平均情况,然后在数字上快速校验和(不是复杂的,因为这可能比排序更糟糕,只是序数的总和),然后排序,然后比较。
If the strings are very short the checksum expense will be not greatly dissimilar to the sort in many languages.
如果字符串很短,那么校验和费用将不会与许多语言中的排序有很大的不同。
#9
1
How about this?
这个怎么样?
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
#10
1
How about Xor'ing both the strings??? This will definitely be of O(n)
那Xor的字符串呢?这肯定是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");
}
}
#11
1
static bool IsAnagram(string s1, string s2)
{
if (s1.Length != s2.Length)
return false;
else
{
int sum1 = 0;
for (int i = 0; i < s1.Length; i++)
sum1 += (int)s1[i]-(int)s2[i];
if (sum1 == 0)
return true;
else
return false;
}
}
#12
1
For known (and small) sets of valid letters (e.g. ASCII) use a table with counts associated with each valid letter. First string increments counts, second string decrements counts. Finally iterate through the table to see if all counts are zero (strings are anagrams) or there are non-zero values (strings are not anagrams). Make sure to convert all characters to uppercase (or lowercase, all the same) and to ignore white space.
对于已知的(和小的)有效字母集合(例如ASCII),使用一个包含每个有效字母的计数表。第一个字符串增量计数,第二个字符串递减计数。最后,遍历表以查看是否所有计数都为零(字符串为anagrams),或者有非零值(字符串不是字谜)。确保将所有字符转换为大写(或小写,所有相同),并忽略空白。
For a large set of valid letters, such as Unicode, do not use table but rather use a hash table. It has O(1) time to add, query and remove and O(n) space. Letters from first string increment count, letters from second string decrement count. Count that becomes zero is removed form the hash table. Strings are anagrams if at the end hash table is empty. Alternatively, search terminates with negative result as soon as any count becomes negative.
对于大量有效的字母,例如Unicode,不要使用表,而是使用散列表。它有O(1)时间来添加、查询和删除和O(n)空间。来自第一个字符串递增计数的字母,第二个字符串递减计数的字母。从哈希表中删除为零的计数。如果最终哈希表是空的,那么字符串就是anagrams。或者,一旦任何计数变为负值,搜索就会终止。
Here is the detailed explanation and implementation in C#: Testing If Two Strings are Anagrams
下面是c#中详细的解释和实现:测试两个字符串是否是字谜。
#13
1
If strings have only ASCII characters:
如果字符串只有ASCII字符:
- create an array of 256 length
- 创建一个256长度的数组。
- traverse the first string and increment counter in the array at index = ascii value of the character. also keep counting characters to find length when you reach end of string
- 在index = ascii值的数组中遍历第一个字符串和递增计数器。当你到达弦的末端时,还要继续计算字符以找到长度。
- traverse the second string and decrement counter in the array at index = ascii value of the character. If the value is ever 0 before decrementing, return false since the strings are not anagrams. also, keep track of the length of this second string.
- 在索引= ascii值的数组中遍历第二个字符串和递减计数器。如果值在递减前为0,则返回false,因为字符串不是anagrams。同时,跟踪第二个字符串的长度。
- at the end of the string traversal, if lengths of the two are equal, return true, else, return false.
- 在字符串遍历的末尾,如果两个长度相等,返回true,否则返回false。
If string can have unicode characters, then use a hash map instead of an array to keep track of the frequency. Rest of the algorithm remains same.
如果字符串可以具有unicode字符,那么可以使用散列映射而不是数组来跟踪频率。算法的其余部分保持不变。
Notes:
注:
- calculating length while adding characters to array ensures that we traverse each string only once.
- 计算长度,同时向数组中添加字符,确保我们只遍历每个字符串一次。
- Using array in case of an ASCII only string optimizes space based on the requirement.
- 在ASCII字符串的情况下使用数组来优化基于需求的空间。
#14
1
let's take a question: Given two strings s and t, write a function to determine if t is an anagram of s.
让我们问一个问题:给定两个字符串s和t,写一个函数来确定t是否是一个s的字型。
For example, s = "anagram", t = "nagaram", return true. s = "rat", t = "car", return false.
例如,s = "anagram", t = "nagaram",返回true。s = "rat", t = "car",返回false。
Method 1(Using HashMap ):
方法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;
}
}
Method 2 :
方法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;
}
}
Method 3 :
方法3:
public class Mathod3 {
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 );
}
}
Method 4 :
方法4:
public class Method4 {
public static void main(String[] args) {
String a = "protijayi";
String b = "jayiproti";
//String c = "gini";
System.out.println(isAnagram(a, b ));// output => true
}
private static boolean isAnagram(String a, String b) {
Map<Integer, Integer> map = new HashMap<>();
a.codePoints().forEach(code -> map.put(code, map.getOrDefault(code, 0) + 1));
b.codePoints().forEach(code -> map.put(code, map.getOrDefault(code, 0) - 1));
//System.out.println(map.values());
for(int count : map.values()) {
if (count<0) return false;
}
return true;
}
}
In Python :
在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))
#15
0
I guess your sorting algorithm is not really O(log n), is it?
我猜你的排序算法不是真的O(log n)吧?
The best you can get is O(n) for your algorithm, because you have to check every character.
你能得到的最好的是O(n)的算法,因为你必须检查每个字符。
You might use two tables to store the counts of each letter in every word, fill it with O(n) and compare it with O(1).
您可以使用两个表来存储每个单词中的每个字母的计数,并将其填入O(n)并与O(1)进行比较。
#16
0
It seems that the following implementation works too, can you check?
看起来下面的实现也有效,您能检查一下吗?
int histogram[256] = {0};
for (int i = 0; i < strlen(str1); ++i) {
/* Just inc and dec every char count and
* check the histogram against 0 in the 2nd loop */
++histo[str1[i]];
--histo[str2[i]];
}
for (int i = 0; i < 256; ++i) {
if (histo[i] != 0)
return 0; /* not an anagram */
}
return 1; /* an anagram */
#17
0
/* Program to find the strings are anagram or not*/
/* Author Senthilkumar M*/
Eg.
Anagram:
str1 = *
str2 = overflowstack
Not anagram:`enter code here`
str1 = stackforflow
str2 = stacknotflow
int is_anagram(char *str1, char *str2)
{
int l1 = strlen(str1);
int l2 = strlen(str2);
int s1 = 0, s2 = 0;
int i = 0;
/* if both the string are not equal it is not anagram*/
if(l1 != l2) {
return 0;
}
/* sum up the character in the strings
if the total sum of the two strings is not equal
it is not anagram */
for( i = 0; i < l1; i++) {
s1 += str1[i];
s2 += str2[i];
}
if(s1 != s2) {
return 0;
}
return 1;
}
#18
0
If both strings are of equal length proceed, if not then the strings are not anagrams.
如果两个字符串是相等的长度,如果不是那么字符串不是字谜。
Iterate each string while summing the ordinals of each character. If the sums are equal then the strings are anagrams.
遍历每个字符串,同时对每个字符的序号进行求和。如果和是相等的,那么弦就是字谜。
Example:
例子:
public Boolean AreAnagrams(String inOne, String inTwo) {
bool result = false;
if(inOne.Length == inTwo.Length) {
int sumOne = 0;
int sumTwo = 0;
for(int i = 0; i < inOne.Length; i++) {
sumOne += (int)inOne[i];
sumTwo += (int)inTwo[i];
}
result = sumOne == sumTwo;
}
return result;
}
#19
0
implementation in Swift 3:
实现快速3:
func areAnagrams(_ str1: String, _ str2: String) -> Bool {
return dictionaryMap(forString: str1) == dictionaryMap(forString: str2)
}
func dictionaryMap(forString str: String) -> [String : Int] {
var dict : [String : Int] = [:]
for var i in 0..<str.characters.count {
if let count = dict[str[i]] {
dict[str[i]] = count + 1
}else {
dict[str[i]] = 1
}
}
return dict
}
//To easily subscript characters
extension String {
subscript(i: Int) -> String {
return String(self[index(startIndex, offsetBy: i)])
}
}
#20
0
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
/**
* --------------------------------------------------------------------------
* Finding Anagrams in the given dictionary. Anagrams are words that can be
* formed from other words Ex :The word "words" can be formed using the word
* "sword"
* --------------------------------------------------------------------------
* Input : if choose option 2 first enter no of word want to compare second
* enter word ex:
*
* Enter choice : 1:To use Test Cases 2: To give input 2 Enter the number of
* words in dictionary
* 6
* viq
* khan
* zee
* khan
* am
*
* Dictionary : [ viq khan zee khan am]
* Anagrams 1:[khan, khan]
*
*/
public class Anagrams {
public static void main(String args[]) {
// User Input or just use the testCases
int choice;
@SuppressWarnings("resource")
Scanner scan = new Scanner(System.in);
System.out.println("Enter choice : \n1:To use Test Cases 2: To give input");
choice = scan.nextInt();
switch (choice) {
case 1:
testCaseRunner();
break;
case 2:
userInput();
default:
break;
}
}
private static void userInput() {
@SuppressWarnings("resource")
Scanner scan = new Scanner(System.in);
System.out.println("Enter the number of words in dictionary");
int number = scan.nextInt();
String dictionary[] = new String[number];
//
for (int i = 0; i < number; i++) {
dictionary[i] = scan.nextLine();
}
printAnagramsIn(dictionary);
}
/**
* provides a some number of dictionary of words
*/
private static void testCaseRunner() {
String dictionary[][] = { { "abc", "cde", "asfs", "cba", "edcs", "name" },
{ "name", "mane", "string", "trings", "embe" } };
for (int i = 0; i < dictionary.length; i++) {
printAnagramsIn(dictionary[i]);
}
}
/**
* Prints the set of anagrams found the give dictionary
*
* logic is sorting the characters in the given word and hashing them to the
* word. Data Structure: Hash[sortedChars] = word
*/
private static void printAnagramsIn(String[] dictionary) {
System.out.print("Dictionary : [");// + dictionary);
for (String each : dictionary) {
System.out.print(each + " ");
}
System.out.println("]");
//
Map<String, ArrayList<String>> map = new LinkedHashMap<String, ArrayList<String>>();
// review comment: naming convention: dictionary contains 'word' not
// 'each'
for (String each : dictionary) {
char[] sortedWord = each.toCharArray();
// sort dic value
Arrays.sort(sortedWord);
//input word
String sortedString = new String(sortedWord);
//
ArrayList<String> list = new ArrayList<String>();
if (map.keySet().contains(sortedString)) {
list = map.get(sortedString);
}
list.add(each);
map.put(sortedString, list);
}
// print anagram
int i = 1;
for (String each : map.keySet()) {
if (map.get(each).size() != 1) {
System.out.println("Anagrams " + i + ":" + map.get(each));
i++;
}
}
}
}
#21
-1
in java we can also do it like this and its very simple logic
在java中,我们也可以这样做,这是非常简单的逻辑。
import java.util.*;
class Anagram
{
public static void main(String args[]) throws Exception
{
Boolean FLAG=true;
Scanner sc= new Scanner(System.in);
System.out.println("Enter 1st string");
String s1=sc.nextLine();
System.out.println("Enter 2nd string");
String s2=sc.nextLine();
int i,j;
i=s1.length();
j=s2.length();
if(i==j)
{
for(int k=0;k<i;k++)
{
for(int l=0;l<i;l++)
{
if(s1.charAt(k)==s2.charAt(l))
{
FLAG=true;
break;
}
else
FLAG=false;
}
}
}
else
FLAG=false;
if(FLAG)
System.out.println("Given Strings are anagrams");
else
System.out.println("Given Strings are not anagrams");
}
}
#22
-1
How about converting into the int value of the character and sum up :
如何转换为字符的int值并求和:
If the value of sum are equals then they are anagram to each other.
如果和的值是相等的,那么它们是相互的。
def are_anagram1(s1, s2):
return [False, True][sum([ord(x) for x in s1]) == sum([ord(x) for x in s2])]
s1 = 'james'
s2 = 'amesj'
print are_anagram1(s1,s2)
This solution works only for 'A' to 'Z' and 'a' to 'z'.
这个解只适用于“A”到“Z”和“A”到“Z”。
#1
51
Count the frequency of each character in the two strings. Check if the two histograms match. O(n) time, O(1) space (assuming ASCII) (Of course it is still O(1) space for Unicode but the table will become very large).
计算两个字符串中每个字符的频率。检查两个直方图是否匹配。O(n)时间,O(1)空间(假设ASCII)(当然,它仍然是Unicode的空间,但表将变得非常大)。
#2
31
Get table of prime numbers, enough to map each prime to every character. So start from 1, going through line, multiply the number by the prime representing current character. Number you'll get is only depend on characters in string but not on their order, and every unique set of characters correspond to unique number, as any number may be factored in only one way. So you can just compare two numbers to say if a strings are anagrams of each other.
获取质数表,足够将每个质数映射到每个字符。所以从1开始,通过直线,将数字乘上代表当前字符的质数。你将得到的数字只取决于字符串中的字符,而不是它们的顺序,并且每一组独特的字符都对应于唯一的数字,因为任何数字都可能只被一个方法分解。所以你可以把两个数字比较一下,如果一个字符串是相互的。
Unfortunately you have to use multiple precision (arbitrary-precision) integer arithmetic to do this, or you will get overflow or rounding exceptions when using this method.
For this you may use libraries like BigInteger
, GMP
, MPIR
or IntX
.
不幸的是,您必须使用多个精度(任意精度)的整数算法来实现这一点,否则在使用此方法时将会出现溢出或舍入异常。为此,您可以使用像BigInteger、GMP、MPIR或IntX这样的库。
Pseudocode:
伪代码:
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)
#3
21
- Create a Hashmap where key - letter and value - frequencey of letter,
- 创建一个Hashmap,其中关键字和值-频率的字母,
- for first string populate the hashmap (O(n))
- 对于第一个字符串填充hashmap (O(n))
- for second string decrement count and remove element from hashmap O(n)
- 对于第二个字符串递减计数,并从hashmap O(n)中删除元素
- if hashmap is empty, the string is anagram otherwise not.
- 如果hashmap为空,则字符串为anagram。
#4
8
The steps are:
的步骤是:
- check the length of of both the words/strings if they are equal then only proceed to check for anagram else do nothing
- 检查单词/字符串的长度,如果它们是相等的,那么只需要检查另一个字母,否则什么也不做。
- sort both the words/strings and then compare
- 对单词/字符串进行排序,然后进行比较。
JAVA CODE TO THE SAME:
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");
}
}
}
#5
3
C#
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);
}
Some tests:
一些测试:
[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"));
}
#6
2
Code to find whether two words are anagrams:
代码查找两个单词是字谜:
Logic explained already in few answers and few asking for the code. This solution produce the result in O(n) time.
逻辑解释已经很少,很少有人问代码。这个解决方案在O(n)时间内产生结果。
This approach counts the no of occurrences of each character and store it in the respective ASCII location for each string. And then compare the two array counts. If it is not equal the given strings are not anagrams.
该方法计算每个字符的出现次数,并将其存储在每个字符串各自的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;
}
#7
2
Using an ASCII hash-map that allows O(1) look-up for each char.
使用允许O(1)查找每个字符的ASCII hashmap。
The java example listed above is converting to lower-case that seems incomplete. I have an example in C that simply initializes a hash-map array for ASCII values to '-1'
上面列出的java示例将转换为不完整的小写。我在C中有一个例子,它简单地将一个hashmap数组初始化为'-1'
If string2 is different in length than string 1, no anagrams
如果string2的长度与字符串1不同,则没有字谜。
Else, we update the appropriate hash-map values to 0 for each char in string1 and string2
另外,我们为string1和string2中的每个char更新适当的hashmap值为0。
Then for each char in string1, we update the count in hash-map. Similarily, we decrement the value of the count for each char in string2.
然后,对于string1中的每个char,我们更新hashmap中的count。类似地,我们递减string2中每个char的值。
The result should have values set to 0 for each char if they are anagrams. if not, some positive value set by string1 remains
如果它们是字谜,结果应该为每个char设置值为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;
}
#8
1
Well you can probably improve the best case and average case substantially just by checking the length first, then a quick checksum on the digits (not something complex, as that will probably be worse order than the sort, just a summation of ordinal values), then sort, then compare.
你可以通过先检查长度来改进最好的情况和平均情况,然后在数字上快速校验和(不是复杂的,因为这可能比排序更糟糕,只是序数的总和),然后排序,然后比较。
If the strings are very short the checksum expense will be not greatly dissimilar to the sort in many languages.
如果字符串很短,那么校验和费用将不会与许多语言中的排序有很大的不同。
#9
1
How about this?
这个怎么样?
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
#10
1
How about Xor'ing both the strings??? This will definitely be of O(n)
那Xor的字符串呢?这肯定是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");
}
}
#11
1
static bool IsAnagram(string s1, string s2)
{
if (s1.Length != s2.Length)
return false;
else
{
int sum1 = 0;
for (int i = 0; i < s1.Length; i++)
sum1 += (int)s1[i]-(int)s2[i];
if (sum1 == 0)
return true;
else
return false;
}
}
#12
1
For known (and small) sets of valid letters (e.g. ASCII) use a table with counts associated with each valid letter. First string increments counts, second string decrements counts. Finally iterate through the table to see if all counts are zero (strings are anagrams) or there are non-zero values (strings are not anagrams). Make sure to convert all characters to uppercase (or lowercase, all the same) and to ignore white space.
对于已知的(和小的)有效字母集合(例如ASCII),使用一个包含每个有效字母的计数表。第一个字符串增量计数,第二个字符串递减计数。最后,遍历表以查看是否所有计数都为零(字符串为anagrams),或者有非零值(字符串不是字谜)。确保将所有字符转换为大写(或小写,所有相同),并忽略空白。
For a large set of valid letters, such as Unicode, do not use table but rather use a hash table. It has O(1) time to add, query and remove and O(n) space. Letters from first string increment count, letters from second string decrement count. Count that becomes zero is removed form the hash table. Strings are anagrams if at the end hash table is empty. Alternatively, search terminates with negative result as soon as any count becomes negative.
对于大量有效的字母,例如Unicode,不要使用表,而是使用散列表。它有O(1)时间来添加、查询和删除和O(n)空间。来自第一个字符串递增计数的字母,第二个字符串递减计数的字母。从哈希表中删除为零的计数。如果最终哈希表是空的,那么字符串就是anagrams。或者,一旦任何计数变为负值,搜索就会终止。
Here is the detailed explanation and implementation in C#: Testing If Two Strings are Anagrams
下面是c#中详细的解释和实现:测试两个字符串是否是字谜。
#13
1
If strings have only ASCII characters:
如果字符串只有ASCII字符:
- create an array of 256 length
- 创建一个256长度的数组。
- traverse the first string and increment counter in the array at index = ascii value of the character. also keep counting characters to find length when you reach end of string
- 在index = ascii值的数组中遍历第一个字符串和递增计数器。当你到达弦的末端时,还要继续计算字符以找到长度。
- traverse the second string and decrement counter in the array at index = ascii value of the character. If the value is ever 0 before decrementing, return false since the strings are not anagrams. also, keep track of the length of this second string.
- 在索引= ascii值的数组中遍历第二个字符串和递减计数器。如果值在递减前为0,则返回false,因为字符串不是anagrams。同时,跟踪第二个字符串的长度。
- at the end of the string traversal, if lengths of the two are equal, return true, else, return false.
- 在字符串遍历的末尾,如果两个长度相等,返回true,否则返回false。
If string can have unicode characters, then use a hash map instead of an array to keep track of the frequency. Rest of the algorithm remains same.
如果字符串可以具有unicode字符,那么可以使用散列映射而不是数组来跟踪频率。算法的其余部分保持不变。
Notes:
注:
- calculating length while adding characters to array ensures that we traverse each string only once.
- 计算长度,同时向数组中添加字符,确保我们只遍历每个字符串一次。
- Using array in case of an ASCII only string optimizes space based on the requirement.
- 在ASCII字符串的情况下使用数组来优化基于需求的空间。
#14
1
let's take a question: Given two strings s and t, write a function to determine if t is an anagram of s.
让我们问一个问题:给定两个字符串s和t,写一个函数来确定t是否是一个s的字型。
For example, s = "anagram", t = "nagaram", return true. s = "rat", t = "car", return false.
例如,s = "anagram", t = "nagaram",返回true。s = "rat", t = "car",返回false。
Method 1(Using HashMap ):
方法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;
}
}
Method 2 :
方法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;
}
}
Method 3 :
方法3:
public class Mathod3 {
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 );
}
}
Method 4 :
方法4:
public class Method4 {
public static void main(String[] args) {
String a = "protijayi";
String b = "jayiproti";
//String c = "gini";
System.out.println(isAnagram(a, b ));// output => true
}
private static boolean isAnagram(String a, String b) {
Map<Integer, Integer> map = new HashMap<>();
a.codePoints().forEach(code -> map.put(code, map.getOrDefault(code, 0) + 1));
b.codePoints().forEach(code -> map.put(code, map.getOrDefault(code, 0) - 1));
//System.out.println(map.values());
for(int count : map.values()) {
if (count<0) return false;
}
return true;
}
}
In Python :
在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))
#15
0
I guess your sorting algorithm is not really O(log n), is it?
我猜你的排序算法不是真的O(log n)吧?
The best you can get is O(n) for your algorithm, because you have to check every character.
你能得到的最好的是O(n)的算法,因为你必须检查每个字符。
You might use two tables to store the counts of each letter in every word, fill it with O(n) and compare it with O(1).
您可以使用两个表来存储每个单词中的每个字母的计数,并将其填入O(n)并与O(1)进行比较。
#16
0
It seems that the following implementation works too, can you check?
看起来下面的实现也有效,您能检查一下吗?
int histogram[256] = {0};
for (int i = 0; i < strlen(str1); ++i) {
/* Just inc and dec every char count and
* check the histogram against 0 in the 2nd loop */
++histo[str1[i]];
--histo[str2[i]];
}
for (int i = 0; i < 256; ++i) {
if (histo[i] != 0)
return 0; /* not an anagram */
}
return 1; /* an anagram */
#17
0
/* Program to find the strings are anagram or not*/
/* Author Senthilkumar M*/
Eg.
Anagram:
str1 = *
str2 = overflowstack
Not anagram:`enter code here`
str1 = stackforflow
str2 = stacknotflow
int is_anagram(char *str1, char *str2)
{
int l1 = strlen(str1);
int l2 = strlen(str2);
int s1 = 0, s2 = 0;
int i = 0;
/* if both the string are not equal it is not anagram*/
if(l1 != l2) {
return 0;
}
/* sum up the character in the strings
if the total sum of the two strings is not equal
it is not anagram */
for( i = 0; i < l1; i++) {
s1 += str1[i];
s2 += str2[i];
}
if(s1 != s2) {
return 0;
}
return 1;
}
#18
0
If both strings are of equal length proceed, if not then the strings are not anagrams.
如果两个字符串是相等的长度,如果不是那么字符串不是字谜。
Iterate each string while summing the ordinals of each character. If the sums are equal then the strings are anagrams.
遍历每个字符串,同时对每个字符的序号进行求和。如果和是相等的,那么弦就是字谜。
Example:
例子:
public Boolean AreAnagrams(String inOne, String inTwo) {
bool result = false;
if(inOne.Length == inTwo.Length) {
int sumOne = 0;
int sumTwo = 0;
for(int i = 0; i < inOne.Length; i++) {
sumOne += (int)inOne[i];
sumTwo += (int)inTwo[i];
}
result = sumOne == sumTwo;
}
return result;
}
#19
0
implementation in Swift 3:
实现快速3:
func areAnagrams(_ str1: String, _ str2: String) -> Bool {
return dictionaryMap(forString: str1) == dictionaryMap(forString: str2)
}
func dictionaryMap(forString str: String) -> [String : Int] {
var dict : [String : Int] = [:]
for var i in 0..<str.characters.count {
if let count = dict[str[i]] {
dict[str[i]] = count + 1
}else {
dict[str[i]] = 1
}
}
return dict
}
//To easily subscript characters
extension String {
subscript(i: Int) -> String {
return String(self[index(startIndex, offsetBy: i)])
}
}
#20
0
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
/**
* --------------------------------------------------------------------------
* Finding Anagrams in the given dictionary. Anagrams are words that can be
* formed from other words Ex :The word "words" can be formed using the word
* "sword"
* --------------------------------------------------------------------------
* Input : if choose option 2 first enter no of word want to compare second
* enter word ex:
*
* Enter choice : 1:To use Test Cases 2: To give input 2 Enter the number of
* words in dictionary
* 6
* viq
* khan
* zee
* khan
* am
*
* Dictionary : [ viq khan zee khan am]
* Anagrams 1:[khan, khan]
*
*/
public class Anagrams {
public static void main(String args[]) {
// User Input or just use the testCases
int choice;
@SuppressWarnings("resource")
Scanner scan = new Scanner(System.in);
System.out.println("Enter choice : \n1:To use Test Cases 2: To give input");
choice = scan.nextInt();
switch (choice) {
case 1:
testCaseRunner();
break;
case 2:
userInput();
default:
break;
}
}
private static void userInput() {
@SuppressWarnings("resource")
Scanner scan = new Scanner(System.in);
System.out.println("Enter the number of words in dictionary");
int number = scan.nextInt();
String dictionary[] = new String[number];
//
for (int i = 0; i < number; i++) {
dictionary[i] = scan.nextLine();
}
printAnagramsIn(dictionary);
}
/**
* provides a some number of dictionary of words
*/
private static void testCaseRunner() {
String dictionary[][] = { { "abc", "cde", "asfs", "cba", "edcs", "name" },
{ "name", "mane", "string", "trings", "embe" } };
for (int i = 0; i < dictionary.length; i++) {
printAnagramsIn(dictionary[i]);
}
}
/**
* Prints the set of anagrams found the give dictionary
*
* logic is sorting the characters in the given word and hashing them to the
* word. Data Structure: Hash[sortedChars] = word
*/
private static void printAnagramsIn(String[] dictionary) {
System.out.print("Dictionary : [");// + dictionary);
for (String each : dictionary) {
System.out.print(each + " ");
}
System.out.println("]");
//
Map<String, ArrayList<String>> map = new LinkedHashMap<String, ArrayList<String>>();
// review comment: naming convention: dictionary contains 'word' not
// 'each'
for (String each : dictionary) {
char[] sortedWord = each.toCharArray();
// sort dic value
Arrays.sort(sortedWord);
//input word
String sortedString = new String(sortedWord);
//
ArrayList<String> list = new ArrayList<String>();
if (map.keySet().contains(sortedString)) {
list = map.get(sortedString);
}
list.add(each);
map.put(sortedString, list);
}
// print anagram
int i = 1;
for (String each : map.keySet()) {
if (map.get(each).size() != 1) {
System.out.println("Anagrams " + i + ":" + map.get(each));
i++;
}
}
}
}
#21
-1
in java we can also do it like this and its very simple logic
在java中,我们也可以这样做,这是非常简单的逻辑。
import java.util.*;
class Anagram
{
public static void main(String args[]) throws Exception
{
Boolean FLAG=true;
Scanner sc= new Scanner(System.in);
System.out.println("Enter 1st string");
String s1=sc.nextLine();
System.out.println("Enter 2nd string");
String s2=sc.nextLine();
int i,j;
i=s1.length();
j=s2.length();
if(i==j)
{
for(int k=0;k<i;k++)
{
for(int l=0;l<i;l++)
{
if(s1.charAt(k)==s2.charAt(l))
{
FLAG=true;
break;
}
else
FLAG=false;
}
}
}
else
FLAG=false;
if(FLAG)
System.out.println("Given Strings are anagrams");
else
System.out.println("Given Strings are not anagrams");
}
}
#22
-1
How about converting into the int value of the character and sum up :
如何转换为字符的int值并求和:
If the value of sum are equals then they are anagram to each other.
如果和的值是相等的,那么它们是相互的。
def are_anagram1(s1, s2):
return [False, True][sum([ord(x) for x in s1]) == sum([ord(x) for x in s2])]
s1 = 'james'
s2 = 'amesj'
print are_anagram1(s1,s2)
This solution works only for 'A' to 'Z' and 'a' to 'z'.
这个解只适用于“A”到“Z”和“A”到“Z”。