Print all pairs of anagrams in a given array of strings
Given an array of strings, find all anagram pairs in the given array.
Example:
Input: arr[] = {"geeksquiz", "geeksforgeeks", "abcd",
"forgeeksgeeks", "zuiqkeegs"};
Output: (geeksforgeeks, forgeeksgeeks), (geeksquiz, zuiqkeegs)
We can find whether two strings are anagram or not in linear time using count array (see method 2 of this).
One simple idea to find whether all anagram pairs is to run two nested loops. The outer loop picks all strings one by one. The inner loop checks whether remaining strings are anagram of the string picked by outer loop.
Below is the implementation of this approach :
C++
#include <bits/stdc++.h>
using namespace std;
#define NO_OF_CHARS 256
bool areAnagram(string str1, string str2)
{
int count[NO_OF_CHARS] = {0};
int i;
for (i = 0; str1[i] && str2[i]; i++)
{
count[str1[i]]++;
count[str2[i]]--;
}
if (str1[i] || str2[i])
return false ;
for (i = 0; i < NO_OF_CHARS; i++)
if (count[i])
return false ;
return true ;
}
void findAllAnagrams(string arr[], int n)
{
for ( int i = 0; i < n; i++)
for ( int j = i+1; j < n; j++)
if (areAnagram(arr[i], arr[j]))
cout << arr[i] << " is anagram of " << arr[j] << endl;
}
int main()
{
string arr[] = { "geeksquiz" , "geeksforgeeks" , "abcd" ,
"forgeeksgeeks" , "zuiqkeegs" };
int n = sizeof (arr)/ sizeof (arr[0]);
findAllAnagrams(arr, n);
return 0;
}
|
Java
public class GFG
{
static final int NO_OF_CHARS = 256 ;
static boolean areAnagram(String str1, String str2)
{
int [] count = new int [NO_OF_CHARS];
int i;
for (i = 0 ; i < str1.length() && i < str2.length();
i++)
{
count[str1.charAt(i)]++;
count[str2.charAt(i)]--;
}
if (str1.length() != str2.length())
return false ;
for (i = 0 ; i < NO_OF_CHARS; i++)
if (count[i] != 0 )
return false ;
return true ;
}
static void findAllAnagrams(String arr[], int n)
{
for ( int i = 0 ; i < n; i++)
for ( int j = i+ 1 ; j < n; j++)
if (areAnagram(arr[i], arr[j]))
System.out.println(arr[i] +
" is anagram of " + arr[j]);
}
public static void main(String args[])
{
String arr[] = { "geeksquiz" , "geeksforgeeks" ,
"abcd" , "forgeeksgeeks" ,
"zuiqkeegs" };
int n = arr.length;
findAllAnagrams(arr, n);
}
}
|
Python3
NO_OF_CHARS = 256
def areAnagram(str1: str , str2: str ) - > bool :
count = [ 0 ] * NO_OF_CHARS
i = 0
while i < len (str1) and i < len (str2):
count[ ord (str1[i])] + = 1
count[ ord (str2[i])] - = 1
i + = 1
if len (str1) ! = len (str2):
return False
for i in range (NO_OF_CHARS):
if count[i]:
return False
return True
def findAllAnagrams(arr: list , n: int ):
for i in range (n):
for j in range (i + 1 , n):
if areAnagram(arr[i], arr[j]):
print (arr[i], "is anagram of" , arr[j])
if __name__ = = "__main__" :
arr = [ "geeksquiz" , "geeksforgeeks" ,
"abcd" , "forgeeksgeeks" , "zuiqkeegs" ]
n = len (arr)
findAllAnagrams(arr, n)
|
C#
using System;
class GFG
{
static int NO_OF_CHARS = 256;
static bool areAnagram(String str1, String str2)
{
int [] count = new int [NO_OF_CHARS];
int i;
for (i = 0; i < str1.Length &&
i < str2.Length; i++)
{
count[str1[i]]++;
count[str2[i]]--;
}
if (str1.Length != str2.Length)
return false ;
for (i = 0; i < NO_OF_CHARS; i++)
if (count[i] != 0)
return false ;
return true ;
}
static void findAllAnagrams(String []arr, int n)
{
for ( int i = 0; i < n; i++)
for ( int j = i+1; j < n; j++)
if (areAnagram(arr[i], arr[j]))
Console.WriteLine(arr[i] +
" is anagram of " + arr[j]);
}
public static void Main()
{
String []arr = { "geeksquiz" , "geeksforgeeks" ,
"abcd" , "forgeeksgeeks" ,
"zuiqkeegs" };
int n = arr.Length;
findAllAnagrams(arr, n);
}
}
|
Javascript
<script>
let NO_OF_CHARS = 256
function areAnagram(str1, str2){
let count = [];
for (let i = 0;i< NO_OF_CHARS;i++)
count[i] = 0;
let i = 0;
while (i < (str1).length && i < (str2).length){
count[ord(str1[i])] += 1;
count[ord(str2[i])] -= 1;
i += 1;
}
if ( (str1).length != (str2).length)
return false ;
for (let i = 0; i < NO_OF_CHARS; i++){
if (count[i])
return false ;
return True;
}
}
function findAllAnagrams(arr, n){
for (let i = 0; i < n; i++){
for (let j = i + 1; j < n; j++){
if areAnagram(arr[i], arr[j])
document.write(arr[i]+ "is anagram of" +arr[j])
}
}
}
let arr = [ "geeksquiz" , "geeksforgeeks" ,
"abcd" , "forgeeksgeeks" , "zuiqkeegs" ];
let n = (arr).length;
findAllAnagrams(arr, n);
</script>
|
Output
geeksquiz is anagram of zuiqkeegs
geeksforgeeks is anagram of forgeeksgeeks
The time complexity of the above solution is O(n2*m) where n is number of strings and m is maximum length of a string.
Auxiliary Space: O(1) or O(256).
Optimizations:
We can optimize the above solution using following approaches.
1) Using sorting: We can sort array of strings so that all anagrams come together. Then print all anagrams by linearly traversing the sorted array. The time complexity of this solution is O(mnLogn) (We would be doing O(nLogn) comparisons in sorting and a comparison would take O(m) time)
Below is the implementation of this approach :
C++
#include <bits/stdc++.h>
using namespace std;
#define NO_OF_CHARS 256
bool areAnagram(string str1, string str2)
{
int count[NO_OF_CHARS] = {0};
int i;
for (i = 0; str1[i] && str2[i]; i++)
{
count[str1[i]]++;
count[str2[i]]--;
}
if (str1[i] || str2[i])
return false ;
for (i = 0; i < NO_OF_CHARS; i++)
if (count[i])
return false ;
return true ;
}
void findAllAnagrams(string arr[], int n)
{
for ( int i = 0; i < n-1; i++) {
for ( int j = i+1; j < n; j++) {
if (areAnagram(arr[i], arr[j]))
cout << arr[i] << " is anagram of " << arr[j] << endl;
}
}
}
int main()
{
string arr[] = { "geeksquiz" , "geeksforgeeks" , "abcd" ,
"forgeeksgeeks" , "zuiqkeegs" };
int n = sizeof (arr)/ sizeof (arr[0]);
findAllAnagrams(arr, n);
return 0;
}
|
Java
import java.util.Arrays;
public class Anagram {
final static int NO_OF_CHARS = 256 ;
static boolean areAnagram(String str1, String str2) {
int [] count = new int [NO_OF_CHARS];
Arrays.fill(count, 0 );
for ( int i = 0 ; i < str1.length() && i < str2.length(); i++) {
count[str1.charAt(i)]++;
count[str2.charAt(i)]--;
}
if (str1.length() != str2.length())
return false ;
for ( int i = 0 ; i < NO_OF_CHARS; i++)
if (count[i] != 0 )
return false ;
return true ;
}
static void findAllAnagrams(String arr[], int n) {
for ( int i = 0 ; i < n - 1 ; i++) {
for ( int j = i + 1 ; j < n; j++) {
if (areAnagram(arr[i], arr[j]))
System.out.println(arr[i] + " is anagram of " + arr[j]);
}
}
}
public static void main(String[] args) {
String[] arr = { "geeksquiz" , "geeksforgeeks" , "abcd" , "forgeeksgeeks" , "zuiqkeegs" };
int n = arr.length;
findAllAnagrams(arr, n);
}
}
|
Python3
NO_OF_CHARS = 256
def areAnagram(str1, str2):
NO_OF_CHARS = 256
count = [ 0 ] * NO_OF_CHARS
for i in range ( max ( len (str1), len (str2))):
if i < len (str1):
count[ ord (str1[i])] + = 1
if i < len (str2):
count[ ord (str2[i])] - = 1
for i in range (NO_OF_CHARS):
if count[i]:
return False
return True
def findAllAnagrams(arr, n):
for i in range (n - 1 ):
for j in range (i + 1 , n):
if areAnagram(arr[i], arr[j]):
print (arr[i], "is anagram of" , arr[j])
if __name__ = = "__main__" :
arr = [ "geeksquiz" , "geeksforgeeks" , "abcd" , "forgeeksgeeks" , "zuiqkeegs" ]
n = len (arr)
findAllAnagrams(arr, n)
|
C#
using System;
public class Anagram
{
const int NO_OF_CHARS = 256;
static bool AreAnagram( string str1, string str2)
{
int [] count = new int [NO_OF_CHARS];
Array.Fill(count, 0);
for ( int i = 0; i < str1.Length && i < str2.Length; i++)
{
count[str1[i]]++;
count[str2[i]]--;
}
if (str1.Length != str2.Length)
return false ;
for ( int i = 0; i < NO_OF_CHARS; i++)
if (count[i] != 0)
return false ;
return true ;
}
static void FindAllAnagrams( string [] arr, int n)
{
for ( int i = 0; i < n - 1; i++)
{
for ( int j = i + 1; j < n; j++)
{
if (AreAnagram(arr[i], arr[j]))
Console.WriteLine(arr[i] + " is anagram of " + arr[j]);
}
}
}
public static void Main( string [] args)
{
string [] arr = { "geeksquiz" , "geeksforgeeks" , "abcd" , "forgeeksgeeks" , "zuiqkeegs" };
int n = arr.Length;
FindAllAnagrams(arr, n);
}
}
|
Javascript
const NO_OF_CHARS = 256;
function areAnagram(str1, str2) {
const count = Array(NO_OF_CHARS).fill(0);
for (let i = 0; i < str1.length && i < str2.length; i++) {
count[str1.charCodeAt(i)]++;
count[str2.charCodeAt(i)]--;
}
if (str1.length != str2.length)
return false ;
for (let i = 0; i < NO_OF_CHARS; i++)
if (count[i])
return false ;
return true ;
}
function findAllAnagrams(arr) {
const n = arr.length;
for (let i = 0; i < n-1; i++) {
for (let j = i+1; j < n; j++) {
if (areAnagram(arr[i], arr[j]))
console.log(`${arr[i]} is anagram of ${arr[j]}`);
}
}
}
const arr = [ "geeksquiz" , "geeksforgeeks" , "abcd" , "forgeeksgeeks" , "zuiqkeegs" ];
findAllAnagrams(arr);
|
Output
geeksquiz is anagram of zuiqkeegs
geeksforgeeks is anagram of forgeeksgeeks
Space complexity :- O(1)
2) Using Hashing: We can build a hash function like XOR or sum of ASCII values of all characters for a string. Using such a hash function, we can build a hash table. While building the hash table, we can check if a value is already hashed. If yes, we can call areAnagrams() to check if two strings are actually anagrams (Note that xor or sum of ASCII values is not sufficient, see Kaushik Lele’s comment here)
Last Updated :
17 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...