Remove minimum characters so that two strings become anagram
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.
Approach - 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) to store the count of characters in both strings.
- 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 absolute difference in counts for each character.
- Sum all the differences to get the total number of deletions required to make the strings anagrams.
- Return the total count of deletions as the result.
// C++ program to find minimum number of characters
// to be removed to make two strings anagram.
#include<bits/stdc++.h>
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;
}
// Java program to find minimum number of characters
// to be removed to make two strings anagram.
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));
}
}
# Python program to find minimum number of characters
# to be removed to make two strings anagram.
# 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))
// C# program to find minimum number of characters
// to be removed to make two strings anagram.
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));
}
}
// JavaScript program to find minimum number of characters
// to be removed to make two strings anagram.
// 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;
}
let str1 = "bcadeh", str2 = "hea";
console.log(remAnagram(str1, str2));
Output
3
Approach - Using One Frequency Array - O(n + m) time and O(1) space
The above solution can be optimized to work with single count array.
// C++ program to find minimum number of characters
// to be removed to make two strings anagram.
#include<bits/stdc++.h>
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;
}
// Java program to find minimum number of characters
// to be removed to make two strings anagram.
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));
}
}
# Python program to find minimum number of characters
# to be removed to make two strings anagram.
# 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))
// C# program to find minimum number of characters
// to be removed to make two strings anagram.
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));
}
}
// JavaScript program to find minimum number of characters
// to be removed to make two strings anagram.
// 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;
}
let str1 = "bcadeh", str2 = "hea";
console.log(remAnagram(str1, str2));
Output
3
Approach - 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).
// C++ program to find minimum number of characters
// to be removed to make two strings anagram.
#include<bits/stdc++.h>
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;
}
// Java program to find minimum number of characters
// to be removed to make two strings anagram.
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));
}
}
# Python program to find minimum number of characters
# to be removed to make two strings anagram.
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))
// C# program to find minimum number of characters
// to be removed to make two strings anagram.
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));
}
}
// JavaScript program to find minimum number of characters
// to be removed to make two strings anagram.
// 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;
}
let str1 = "bcadeh", str2 = "hea";
console.log(remAnagram(str1, str2));
Output
3