Two strings s1 and s2 are called isomorphic if there is a one-to-one mapping possible for every character of s1 to every character of s2. And all occurrences of every character in 's1' map to the same character in 's2'.
Examples:
Input: s1 = "aab", s2 = "xxy"
Output: True
Explanation: 'a' is mapped to 'x' and 'b' is mapped to 'y'.
Input: s1 = "aab", s2 = "xyz"
Output: False
Explanation: One occurrence of 'a' in s1 has 'x' in s2 and other occurrence of 'a' has 'y'.
[Naive Approach] Check Every Character - O(n^2) Time and O(1) Space
A Simple Solution is to consider every character of 's1' and check if all occurrences of it map to the same character in 's2'.
C++
#include <iostream>
#include <string>
using namespace std;
bool areIsomorphic(string s1, string s2)
{
// If lengths are different, they can't be isomorphic
if (s1.length() != s2.length())
{
return false;
}
int n = s1.length();
// Check every character of s1
for (int i = 0; i < n; i++)
{
char c1 = s1[i];
char c2 = s2[i];
// Check all occurrences of c1 in s1
// and corresponding occurrences of c2 in s2
for (int j = 0; j < n; j++)
{
// If we find another occurrence of c1 in s1,
// it must match the corresponding character in s2
if (s1[j] == c1 && s2[j] != c2)
{
return false;
}
// If we find another occurrence of c2 in s2,
// it must match the corresponding character in s1
if (s2[j] == c2 && s1[j] != c1)
{
return false;
}
}
}
return true;
}
int main()
{
string s1 = "aab";
string s2 = "xxy";
if (areIsomorphic(s1, s2))
{
cout << "True\n";
}
else
{
cout << "False\n";
}
return 0;
}
Java
import java.util.HashMap;
import java.util.Map;
public class GfG {
public static boolean areIsomorphic(String s1,
String s2)
{
// If lengths are different, they can't be
// isomorphic
if (s1.length() != s2.length()) {
return false;
}
Map<Character, Character> map1 = new HashMap<>();
Map<Character, Character> map2 = new HashMap<>();
for (int i = 0; i < s1.length(); i++) {
char c1 = s1.charAt(i);
char c2 = s2.charAt(i);
// Check mapping for s1 to s2
if (map1.containsKey(c1)
&& map1.get(c1) != c2) {
return false;
}
map1.put(c1, c2);
// Check mapping for s2 to s1
if (map2.containsKey(c2)
&& map2.get(c2) != c1) {
return false;
}
map2.put(c2, c1);
}
return true;
}
public static void main(String[] args)
{
String s1 = "aab";
String s2 = "xxy";
if (areIsomorphic(s1, s2)) {
System.out.println("True");
}
else {
System.out.println("False");
}
}
}
Python
# Python implementation
def are_isomorphic(s1, s2):
# If lengths are different, they can't be isomorphic
if len(s1) != len(s2):
return False
map1, map2 = {}, {}
for c1, c2 in zip(s1, s2):
# Check mapping for s1 to s2
if c1 in map1:
if map1[c1] != c2:
return False
else:
map1[c1] = c2
# Check mapping for s2 to s1
if c2 in map2:
if map2[c2] != c1:
return False
else:
map2[c2] = c1
return True
s1 = "aab"
s2 = "xxy"
if are_isomorphic(s1, s2):
print("True")
else:
print("False")
C#
using System;
using System.Collections.Generic;
class GfG {
public static bool AreIsomorphic(string s1, string s2)
{
// If lengths are different, they can't be
// isomorphic
if (s1.Length != s2.Length) {
return false;
}
Dictionary<char, char> map1
= new Dictionary<char, char>();
Dictionary<char, char> map2
= new Dictionary<char, char>();
for (int i = 0; i < s1.Length; i++) {
char c1 = s1[i];
char c2 = s2[i];
// Check mapping for s1 to s2
if (map1.ContainsKey(c1) && map1[c1] != c2) {
return false;
}
map1[c1] = c2;
// Check mapping for s2 to s1
if (map2.ContainsKey(c2) && map2[c2] != c1) {
return false;
}
map2[c2] = c1;
}
return true;
}
static void Main()
{
string s1 = "aab";
string s2 = "xxy";
if (AreIsomorphic(s1, s2)) {
Console.WriteLine("True");
}
else {
Console.WriteLine("False");
}
}
}
JavaScript
function areIsomorphic(s1, s2)
{
// If lengths are different, they can't be isomorphic
if (s1.length !== s2.length) {
return false;
}
const map1 = {};
const map2 = {};
for (let i = 0; i < s1.length; i++) {
const c1 = s1[i];
const c2 = s2[i];
// Check mapping for s1 to s2
if (map1[c1] !== undefined && map1[c1] !== c2) {
return false;
}
map1[c1] = c2;
// Check mapping for s2 to s1
if (map2[c2] !== undefined && map2[c2] !== c1) {
return false;
}
map2[c2] = c1;
}
return true;
}
const s1 = "aab";
const s2 = "xxy";
if (areIsomorphic(s1, s2)) {
console.log("True");
}
else {
console.log("False");
}
[Approach 1] Using Hash Maps - O(n) time and O(MAX_CHAR) space
The idea is based on the fact that all occurrences of two characters should be at same index. We mainly store the first index of every character and for remaining occurrences, we check if they appear at same first index too.
We mainly use two maps m1 and m2 to store characters as keys and their first indexes as values.
- If the lengths of s1 and s2 are not same, return false.
- Do the following for every character in s1 and s2.
- If this character is seen first time in s1, then store is index in map m1.
- If this character is seen first time in s2, then store is index in map m2.
- If indexes in map for both the characters do not match, return false.
C++
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
bool isIsomorphic(const string &s1, const string &s2)
{
if (s1.length() != s2.length())
return false;
unordered_map<char, int> m1, m2;
for (int i = 0; i < s1.length(); ++i)
{
// If character not seen before, store its
// first occurrence index
if (m1.find(s1[i]) == m1.end())
{
m1[s1[i]] = i;
}
if (m2.find(s2[i]) == m2.end())
{
m2[s2[i]] = i;
}
// Check if the first occurrence indices match
if (m1[s1[i]] != m2[s2[i]])
{
return false;
}
}
return true;
}
int main()
{
cout << (isIsomorphic("aab", "xxy") ? "True" : "False");
return 0;
}
Java
import java.util.HashMap;
import java.util.Map;
public class GfG{
public static boolean isIsomorphic(String s1, String s2)
{
if (s1.length() != s2.length())
return false;
Map<Character, Integer> m1 = new HashMap<>();
Map<Character, Integer> m2 = new HashMap<>();
for (int i = 0; i < s1.length(); ++i) {
// If character not seen before, store its
// first occurrence index
if (!m1.containsKey(s1.charAt(i))) {
m1.put(s1.charAt(i), i);
}
if (!m2.containsKey(s2.charAt(i))) {
m2.put(s2.charAt(i), i);
}
// Check if the first occurrence indices match
if (!m1.get(s1.charAt(i))
.equals(m2.get(s2.charAt(i)))) {
return false;
}
}
return true;
}
public static void main(String[] args)
{
System.out.println(
isIsomorphic("aab", "xxy") ? "True" : "False");
}
}
Python
def is_isomorphic(s1, s2):
if len(s1) != len(s2):
return False
m1, m2 = {}, {}
for i in range(len(s1)):
# If character not seen before, store
# its first occurrence index
if s1[i] not in m1:
m1[s1[i]] = i
if s2[i] not in m2:
m2[s2[i]] = i
# Check if the first occurrence indices match
if m1[s1[i]] != m2[s2[i]]:
return False
return True
print("True" if is_isomorphic("aab", "xxy") else "False")
C#
using System;
using System.Collections.Generic;
class GfG {
static bool IsIsomorphic(string s1, string s2)
{
if (s1.Length != s2.Length)
return false;
Dictionary<char, int> m1
= new Dictionary<char, int>();
Dictionary<char, int> m2
= new Dictionary<char, int>();
for (int i = 0; i < s1.Length; ++i) {
// If character not seen before, store its first
// occurrence index
if (!m1.ContainsKey(s1[i])) {
m1[s1[i]] = i;
}
if (!m2.ContainsKey(s2[i])) {
m2[s2[i]] = i;
}
// Check if the first occurrence indices match
if (m1[s1[i]] != m2[s2[i]]) {
return false;
}
}
return true;
}
static void Main()
{
Console.WriteLine(
IsIsomorphic("aab", "xxy") ? "True" : "False");
}
}
JavaScript
function isIsomorphic(s1, s2)
{
if (s1.length !== s2.length)
return false;
const m1 = {}, m2 = {};
for (let i = 0; i < s1.length; i++) {
// If character not seen before, store its first
// occurrence index
if (!(s1[i] in m1)) {
m1[s1[i]] = i;
}
if (!(s2[i] in m2)) {
m2[s2[i]] = i;
}
// Check if the first occurrence indices match
if (m1[s1[i]] !== m2[s2[i]]) {
return false;
}
}
return true;
}
console.log(isIsomorphic("aab", "xxy") ? "True" : "False");
[Approach 2] Further Optimization using a Fixed Array of size 256
We can avoid the language specific hash function computation and use our own fixed sized array using the fact that the alphabet size 256.
C++
#include <iostream>
#include <vector>
#include <string>
using namespace std;
const int MAX_CHAR = 256;
bool isIsomorphic(const string &s1, const string &s2) {
if (s1.length() != s2.length()) return false;
// To store first indices of s1's characters
vector<int> m1(MAX_CHAR, -1);
// To store first indices of s2's characters
vector<int> m2(MAX_CHAR, -1);
for (int i = 0; i < s1.length(); ++i) {
// If character's first occurrence hasn't been
// recorded, store the index
if (m1[s1[i]] == -1) {
m1[s1[i]] = i;
}
if (m2[s2[i]] == -1) {
m2[s2[i]] = i;
}
// Check if the first occurrence indices match
if (m1[s1[i]] != m2[s2[i]]) {
return false;
}
}
return true;
}
int main() {
cout << (isIsomorphic("aab", "xxy") ? "True" : "False") << endl;
return 0;
}
Java
import java.util.HashMap;
import java.util.Map;
public class IsomorphicStrings {
public static boolean isIsomorphic(String s1, String s2) {
if (s1.length() != s2.length()) return false;
// To store first indices of s1's characters
Map<Character, Integer> m1 = new HashMap<>();
// To store first indices of s2's characters
Map<Character, Integer> m2 = new HashMap<>();
for (int i = 0; i < s1.length(); i++) {
// If character's first occurrence hasn't been
// recorded, store the index
m1.putIfAbsent(s1.charAt(i), i);
m2.putIfAbsent(s2.charAt(i), i);
// Check if the first occurrence indices match
if (!m1.get(s1.charAt(i)).equals(m2.get(s2.charAt(i)))) {
return false;
}
}
return true;
}
public static void main(String[] args) {
System.out.println(isIsomorphic("aab", "xxy") ? "True" : "False");
}
}
Python
def is_isomorphic(s1, s2):
if len(s1) != len(s2):
return False
# To store first indices of s1's characters
m1 = {}
# To store first indices of s2's characters
m2 = {}
for i in range(len(s1)):
# If character's first occurrence hasn't been
# recorded, store the index
if s1[i] not in m1:
m1[s1[i]] = i
if s2[i] not in m2:
m2[s2[i]] = i
# Check if the first occurrence indices match
if m1[s1[i]] != m2[s2[i]]:
return False
return True
print("True" if is_isomorphic("aab", "xxy") else "False")
C#
using System;
using System.Collections.Generic;
class Program {
static bool IsIsomorphic(string s1, string s2) {
if (s1.Length != s2.Length) return false;
// To store first indices of s1's characters
Dictionary<char, int> m1 = new Dictionary<char, int>();
// To store first indices of s2's characters
Dictionary<char, int> m2 = new Dictionary<char, int>();
for (int i = 0; i < s1.Length; i++) {
// If character's first occurrence hasn't been
// recorded, store the index
if (!m1.ContainsKey(s1[i])) m1[s1[i]] = i;
if (!m2.ContainsKey(s2[i])) m2[s2[i]] = i;
// Check if the first occurrence indices match
if (m1[s1[i]] != m2[s2[i]]) {
return false;
}
}
return true;
}
static void Main() {
Console.WriteLine(IsIsomorphic("aab", "xxy") ? "True" : "False");
}
}
JavaScript
function isIsomorphic(s1, s2) {
if (s1.length !== s2.length) return false;
// To store first indices of s1's characters
const m1 = {};
// To store first indices of s2's characters
const m2 = {};
for (let i = 0; i < s1.length; i++) {
// If character's first occurrence hasn't been
// recorded, store the index
if (!(s1[i] in m1)) m1[s1[i]] = i;
if (!(s2[i] in m2)) m2[s2[i]] = i;
// Check if the first occurrence indices match
if (m1[s1[i]] !== m2[s2[i]]) {
return false;
}
}
return true;
}
console.log(isIsomorphic("aab", "xxy") ? "True" : "False");
[Approach 3] Using a Set instead of Map for s2- O(n) Time and O(MAX_CHAR) Space
The idea is to store mapping of characters from s1 to s2 in a map and already seen characters of s2 in a set.
Follow the steps to solve the problem:
- Create a hashmap of (char, char) to store the mapping of s1 and s2.
- Now traverse on the string and check whether the current character is present in the Hash map.
- If it is present then the character that is mapped is there at the ith index or not.
- Else If s2[i] is present in the set then s2[i] is already mapped to something else, return false
- Else store mapping of both characters and store s2[i] in the set.
C++
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <string>
using namespace std;
bool isIsomorphic(const string &s1, const string &s2) {
if (s1.length() != s2.length()) return false;
// character mapping from s1 to s2
unordered_map<char, char> m1;
// Already mapped characters in s2
unordered_set<char> set2;
for (int i = 0; i < s1.length(); ++i) {
char c1 = s1[i], c2 = s2[i];
// If c1 is already mapped
if (m1.find(c1) != m1.end()) {
// Check if it maps to the current
// character in s2
if (m1[c1] != c2) return false;
}
// First occurrence of c1
else {
// Ensure c2 is not already mapped
// to another character
if (set2.find(c2) != set2.end()) return false;
// Create a new mapping and mark c2 as mapped
m1[c1] = c2;
set2.insert(c2);
}
}
return true;
}
int main() {
cout << (isIsomorphic("aab", "xxy") ? "True" : "False") << endl;
return 0;
}
Java
import java.util.HashMap;
import java.util.HashSet;
public class Main {
public static boolean isIsomorphic(String s1, String s2) {
if (s1.length() != s2.length()) return false;
// character mapping from s1 to s2
HashMap<Character, Character> m1 = new HashMap<>();
// Already mapped characters in s2
HashSet<Character> set2 = new HashSet<>();
for (int i = 0; i < s1.length(); i++) {
char c1 = s1.charAt(i), c2 = s2.charAt(i);
// If c1 is already mapped
if (m1.containsKey(c1)) {
// Check if it maps to the current character in s2
if (m1.get(c1) != c2) return false;
} else {
// Ensure c2 is not already mapped to another character
if (set2.contains(c2)) return false;
// Create a new mapping and mark c2 as mapped
m1.put(c1, c2);
set2.add(c2);
}
}
return true;
}
public static void main(String[] args) {
System.out.println(isIsomorphic("aab", "xxy") ? "True" : "False");
}
}
Python
def is_isomorphic(s1, s2):
if len(s1) != len(s2):
return False
# character mapping from s1 to s2
m1 = {}
# Already mapped characters in s2
set2 = set()
for c1, c2 in zip(s1, s2):
# If c1 is already mapped
if c1 in m1:
# Check if it maps to the current character in s2
if m1[c1] != c2:
return False
else:
# Ensure c2 is not already mapped to another character
if c2 in set2:
return False
# Create a new mapping and mark c2 as mapped
m1[c1] = c2
set2.add(c2)
return True
if __name__ == '__main__':
print("True" if is_isomorphic("aab", "xxy") else "False")
C#
using System;
using System.Collections.Generic;
class Program {
public static bool IsIsomorphic(string s1, string s2) {
if (s1.Length != s2.Length) return false;
// character mapping from s1 to s2
Dictionary<char, char> m1 = new Dictionary<char, char>();
// Already mapped characters in s2
HashSet<char> set2 = new HashSet<char>();
for (int i = 0; i < s1.Length; i++) {
char c1 = s1[i], c2 = s2[i];
// If c1 is already mapped
if (m1.ContainsKey(c1)) {
// Check if it maps to the current character in s2
if (m1[c1] != c2) return false;
} else {
// Ensure c2 is not already mapped to another character
if (set2.Contains(c2)) return false;
// Create a new mapping and mark c2 as mapped
m1[c1] = c2;
set2.Add(c2);
}
}
return true;
}
static void Main() {
Console.WriteLine(IsIsomorphic("aab", "xxy") ? "True" : "False");
}
}
JavaScript
function isIsomorphic(s1, s2) {
if (s1.length !== s2.length) return false;
// character mapping from s1 to s2
const m1 = {};
// Already mapped characters in s2
const set2 = new Set();
for (let i = 0; i < s1.length; i++) {
const c1 = s1[i], c2 = s2[i];
// If c1 is already mapped
if (m1[c1]) {
// Check if it maps to the current character in s2
if (m1[c1] !== c2) return false;
} else {
// Ensure c2 is not already mapped to another character
if (set2.has(c2)) return false;
// Create a new mapping and mark c2 as mapped
m1[c1] = c2;
set2.add(c2);
}
}
return true;
}
console.log(isIsomorphic("aab", "xxy") ? "True" : "False");
This method can also be further optimized using fixed sized arrays of size 256 instead of map and set.
Similar Reads
Check if a string is Isogram or not
Given a word or phrase, check if it is an isogram or not. An Isogram is a word in which no letter occurs more than once Examples: Input: MachineOutput: TrueExplanation: "Machine" does not have any character repeating, it is an Isogram Input : GeekOutput : FalseExplanation: "Geek" has 'e' as repeatin
9 min read
Check for Binary String
Given a string s, the task is to check if it is a binary string or not. A binary string is a string which only contains the characters '0' and '1'.Examples:Input: s = "01010101010"Output: trueInput: s = "geeks101"Output: false Approach:The idea is to iterate over all the characters of the string and
3 min read
Check if a string is Colindrome
Given a string, check if it is Colindrome or not. A string is said to be colindrome if it has consecutive 3 alphabets followed by the reverse of these 3 alphabets and so on. Examples : Input : cappaccappac Output : String is colindrome Input : mollomaappaa Output : String is Colindrome Approach : Ta
6 min read
Check if a string is Pangrammatic Lipogram
To understand what a pangrammatic lipogram is we will break this term down into 2 terms i.e. a pangram and a lipogram Pangram: A pangram or holoalphabetic sentence is a sentence using every letter of a given alphabet at least once. The best-known English pangram is "The quick brown fox jumps over th
14 min read
Check if two strings are same or not
Given two strings, the task is to check if these two strings are identical(same) or not. Consider case sensitivity.Examples:Input: s1 = "abc", s2 = "abc" Output: Yes Input: s1 = "", s2 = "" Output: Yes Input: s1 = "GeeksforGeeks", s2 = "Geeks" Output: No Approach - By Using (==) in C++/Python/C#, eq
7 min read
Check if given String is Pangram or not
Given a string s, the task is to check if it is Pangram or not. A pangram is a sentence containing all letters of the English Alphabet.Examples: Input: s = "The quick brown fox jumps over the lazy dog" Output: trueExplanation: The input string contains all characters from âaâ to âzâ.Input: s = "The
6 min read
Bitonic string
Given a string str, the task is to check if that string is a Bitonic String or not. If string str is Bitonic String then print "YES" else print "NO". A Bitonic String is a string in which the characters are arranged in increasing order followed by decreasing order of their ASCII values. Examples: In
6 min read
Spell Checker using Trie
Given an array of strings str[] and a string key, the task is to check if the spelling of the key is correct or not. If found to be true, then print "YES". Otherwise, print the suggested correct spellings. Examples: Input:str[] = { âgeeâ, âgeeksâ, âapeâ, âappleâ, âgeeksforgeeksâ }, key = âgeekâ Outp
11 min read
POTD Solutions | 11 Novâ 23 | Isomorphic Strings
View all POTD Solutions Welcome to the daily solutions of our PROBLEM OF THE DAY (POTD). We will discuss the entire problem step-by-step and work towards developing an optimized solution. This will not only help you brush up on your concepts of String but will also help you build up problem-solving
5 min read
Check if all given strings are isograms or not
Given an array arr containing N strings, the task is to check if all strings are isogram or not. If they are, print Yes, otherwise No. An Isogram is a word in which no letter occurs more than once. Examples: Input: arr[] = {"abcd", "derg", "erty"}Output: Yes Input: arr[] = {"agka", "lkmn"}Output: No
4 min read