Given two strings in lowercase, the task is to make them anagrams. The only allowed operation is to remove a character from any string. Find the minimum number of characters to be deleted to make both the strings anagram. Two strings are called anagrams of each other if one of them can be converted into another by rearranging its letters.
Examples :
Input : s1 = "bcadeh", s2 = "hea"
Output: 3
Explanation: We need to remove b, c and d from s1.
Input : s1 = "cddgk", s2 = "gcda"
Output: 3
Explanation: Remove one occurrence of d and k from s1 and one occurrence of a from s2.
Input : s1 = "bca", s2 = "acb"
Output: 0
Explanation: Strings are already anagrams.
Table of Content
Using 2 Frequency Arrays - O(n + m) Time and O(1) Space
The idea is to use frequency counting to determine the number of characters that need to be removed from both strings to make them anagrams. By comparing the frequency of each character in both strings, we can calculate the total number of deletions required to balance the frequencies.
Step by step approach:
- Initialize two frequency arrays of size 26 (for each lowercase letter).
- Traverse the first string and increment the count of each character in the first frequency array.
- Traverse the second string and increment the count of each character in the second frequency array.
- Traverse both frequency arrays and calculate the sum of absolute differences in counts for each character.
- Return the total count of deletions as the result.
#include<iostream>
using namespace std;
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
int remAnagram(string& s1, string& s2) {
vector<int> cnt1(26, 0);
vector<int> cnt2(26, 0);
// count frequency of each character in first string
for (char ch: s1) {
cnt1[ch-'a']++;
}
// count frequency of each character in second string
for (char ch: s2) {
cnt2[ch-'a']++;
}
// traverse count arrays to find number of characters
// to be removed
int ans = 0;
for (int i=0; i<26; i++)
ans += abs(cnt1[i] - cnt2[i]);
return ans;
}
int main() {
string str1 = "bcadeh", str2 = "hea";
cout << remAnagram(str1, str2);
return 0;
}
import java.util.*;
class GfG {
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
static int remAnagram(String s1, String s2) {
int[] cnt1 = new int[26];
int[] cnt2 = new int[26];
// count frequency of each character in first string
for (char ch : s1.toCharArray()) {
cnt1[ch - 'a']++;
}
// count frequency of each character in second string
for (char ch : s2.toCharArray()) {
cnt2[ch - 'a']++;
}
// traverse count arrays to find number of characters
// to be removed
int ans = 0;
for (int i = 0; i < 26; i++)
ans += Math.abs(cnt1[i] - cnt2[i]);
return ans;
}
public static void main(String[] args) {
String str1 = "bcadeh", str2 = "hea";
System.out.println(remAnagram(str1, str2));
}
}
# function to calculate minimum numbers of characters
# to be removed to make two strings anagram
def remAnagram(s1, s2):
cnt1 = [0] * 26
cnt2 = [0] * 26
# count frequency of each character in first string
for ch in s1:
cnt1[ord(ch) - ord('a')] += 1
# count frequency of each character in second string
for ch in s2:
cnt2[ord(ch) - ord('a')] += 1
# traverse count arrays to find number of characters
# to be removed
ans = 0
for i in range(26):
ans += abs(cnt1[i] - cnt2[i])
return ans
if __name__ == "__main__":
str1 = "bcadeh"
str2 = "hea"
print(remAnagram(str1, str2))
using System;
class GfG {
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
static int remAnagram(string s1, string s2) {
int[] cnt1 = new int[26];
int[] cnt2 = new int[26];
// count frequency of each character in first string
foreach (char ch in s1) {
cnt1[ch - 'a']++;
}
// count frequency of each character in second string
foreach (char ch in s2) {
cnt2[ch - 'a']++;
}
// traverse count arrays to find number of characters
// to be removed
int ans = 0;
for (int i = 0; i < 26; i++)
ans += Math.Abs(cnt1[i] - cnt2[i]);
return ans;
}
static void Main() {
string str1 = "bcadeh", str2 = "hea";
Console.WriteLine(remAnagram(str1, str2));
}
}
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
function remAnagram(s1, s2) {
let cnt1 = new Array(26).fill(0);
let cnt2 = new Array(26).fill(0);
// count frequency of each character in first string
for (let ch of s1) {
cnt1[ch.charCodeAt(0) - 'a'.charCodeAt(0)]++;
}
// count frequency of each character in second string
for (let ch of s2) {
cnt2[ch.charCodeAt(0) - 'a'.charCodeAt(0)]++;
}
// traverse count arrays to find number of characters
// to be removed
let ans = 0;
for (let i = 0; i < 26; i++)
ans += Math.abs(cnt1[i] - cnt2[i]);
return ans;
}
// Driver Code
let str1 = "bcadeh", str2 = "hea";
console.log(remAnagram(str1, str2));
Output
3
Using One Frequency Array - O(n + m) Time and O(1) Space
The idea is to use one count array, increment frequencies for first string and decrease for second string.
- Create a single frequency array.
- Increment frequency for each character in the count array.
- Decrement frequency of each character in the same array.
- Return sum of absolute values in the frequency array.
#include<iostream>
using namespace std;
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
int remAnagram(string& s1, string& s2) {
vector<int> cnt(26, 0);
// increment frequency of each character in first string
for (char ch: s1) {
cnt[ch-'a']++;
}
// decrement frequency of each character in second string
for (char ch: s2) {
cnt[ch-'a']--;
}
// traverse count array to find number of characters
// to be removed
int ans = 0;
for (int i=0; i<26; i++)
ans += abs(cnt[i]);
return ans;
}
int main() {
string str1 = "bcadeh", str2 = "hea";
cout << remAnagram(str1, str2);
return 0;
}
import java.util.*;
class GfG {
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
static int remAnagram(String s1, String s2) {
int[] cnt = new int[26];
// increment frequency of each character in first string
for (char ch : s1.toCharArray()) {
cnt[ch - 'a']++;
}
// decrement frequency of each character in second string
for (char ch : s2.toCharArray()) {
cnt[ch - 'a']--;
}
// traverse count array to find number of characters
// to be removed
int ans = 0;
for (int i = 0; i < 26; i++)
ans += Math.abs(cnt[i]);
return ans;
}
public static void main(String[] args) {
String str1 = "bcadeh", str2 = "hea";
System.out.println(remAnagram(str1, str2));
}
}
# function to calculate minimum numbers of characters
# to be removed to make two strings anagram
def remAnagram(s1, s2):
cnt = [0] * 26
# increment frequency of each character in first string
for ch in s1:
cnt[ord(ch) - ord('a')] += 1
# decrement frequency of each character in second string
for ch in s2:
cnt[ord(ch) - ord('a')] -= 1
# traverse count array to find number of characters
# to be removed
ans = sum(abs(x) for x in cnt)
return ans
if __name__ == "__main__":
str1 = "bcadeh"
str2 = "hea"
print(remAnagram(str1, str2))
using System;
class GfG {
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
static int remAnagram(string s1, string s2) {
int[] cnt = new int[26];
// increment frequency of each character in first string
foreach (char ch in s1) {
cnt[ch - 'a']++;
}
// decrement frequency of each character in second string
foreach (char ch in s2) {
cnt[ch - 'a']--;
}
// traverse count array to find number of characters
// to be removed
int ans = 0;
for (int i = 0; i < 26; i++)
ans += Math.Abs(cnt[i]);
return ans;
}
static void Main() {
string str1 = "bcadeh", str2 = "hea";
Console.WriteLine(remAnagram(str1, str2));
}
}
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
function remAnagram(s1, s2) {
let cnt = new Array(26).fill(0);
// increment frequency of each character in first string
for (let ch of s1) {
cnt[ch.charCodeAt(0) - 'a'.charCodeAt(0)]++;
}
// decrement frequency of each character in second string
for (let ch of s2) {
cnt[ch.charCodeAt(0) - 'a'.charCodeAt(0)]--;
}
// traverse count array to find number of characters
// to be removed
let ans = 0;
for (let i = 0; i < 26; i++)
ans += Math.abs(cnt[i]);
return ans;
}
// Driver Code
let str1 = "bcadeh", str2 = "hea";
console.log(remAnagram(str1, str2));
Output
3
Using Hash Map - O(n + m) Time and O(1) Space
The idea is similar to the first two approaches, but instead of using an array, hash map is used. This approach is useful when the strings can contain different types of characters (lowercase, uppercase, special symbols).
#include<iostream>
using namespace std;
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
int remAnagram(string& s1, string& s2) {
unordered_map<char, int> map;
// increment frequency of each character in first string
for (char ch: s1) {
map[ch]++;
}
// decrement frequency of each character in second string
for (char ch: s2) {
map[ch]--;
}
// traverse count array to find number of characters
// to be removed
int ans = 0;
for (auto p: map)
ans += abs(p.second);
return ans;
}
int main() {
string str1 = "bcadeh", str2 = "hea";
cout << remAnagram(str1, str2);
return 0;
}
import java.util.*;
class GfG {
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
static int remAnagram(String s1, String s2) {
Map<Character, Integer> map = new HashMap<>();
// increment frequency of each character in first string
for (char ch : s1.toCharArray()) {
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
// decrement frequency of each character in second string
for (char ch : s2.toCharArray()) {
map.put(ch, map.getOrDefault(ch, 0) - 1);
}
// traverse count array to find number of characters
// to be removed
int ans = 0;
for (int count : map.values())
ans += Math.abs(count);
return ans;
}
public static void main(String[] args) {
String str1 = "bcadeh", str2 = "hea";
System.out.println(remAnagram(str1, str2));
}
}
from collections import defaultdict
# function to calculate minimum numbers of characters
# to be removed to make two strings anagram
def remAnagram(s1, s2):
map = defaultdict(int)
# increment frequency of each character in first string
for ch in s1:
map[ch] += 1
# decrement frequency of each character in second string
for ch in s2:
map[ch] -= 1
# traverse count array to find number of characters
# to be removed
ans = sum(abs(count) for count in map.values())
return ans
if __name__ == "__main__":
str1 = "bcadeh"
str2 = "hea"
print(remAnagram(str1, str2))
using System;
using System.Collections.Generic;
class GfG {
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
static int remAnagram(string s1, string s2) {
Dictionary<char, int> map = new Dictionary<char, int>();
// increment frequency of each character in first string
foreach (char ch in s1) {
if (map.ContainsKey(ch))
map[ch]++;
else
map[ch] = 1;
}
// decrement frequency of each character in second string
foreach (char ch in s2) {
if (map.ContainsKey(ch))
map[ch]--;
else
map[ch] = -1;
}
// traverse count array to find number of characters
// to be removed
int ans = 0;
foreach (int count in map.Values)
ans += Math.Abs(count);
return ans;
}
static void Main() {
string str1 = "bcadeh", str2 = "hea";
Console.WriteLine(remAnagram(str1, str2));
}
}
// function to calculate minimum numbers of characters
// to be removed to make two strings anagram
function remAnagram(s1, s2) {
let map = new Map();
// increment frequency of each character in first string
for (let ch of s1) {
map.set(ch, (map.get(ch) || 0) + 1);
}
// decrement frequency of each character in second string
for (let ch of s2) {
map.set(ch, (map.get(ch) || 0) - 1);
}
// traverse count array to find number of characters
// to be removed
let ans = 0;
for (let count of map.values())
ans += Math.abs(count);
return ans;
}
// Driver Code
let str1 = "bcadeh", str2 = "hea";
console.log(remAnagram(str1, str2));
Output
3