Most Efficient & Simpler Solution
This approach uses just 1 HashMap & makes 1 traversal on the input string and the HashMap.
Procedure:
- Populate the HashMap with the frequencies of each Character.
- Now iterate through this HashMap and find the maxFrequency, minFrequency, & count of occurrences of maxFrequency.
- Now using these 3 variables check if the given constraints of the problem are satisfied or not (as shown in the below mentioned code).
#include <iostream>
#include <unordered_map>
#include <climits> // Include for INT_MIN and INT_MAX
using namespace std;
bool sameFreq(string s) {
unordered_map<char, int> freqMap;
// Logic to populate the frequency of each character.
for (int i = 0; i < s.length(); i++) {
freqMap[s[i]]++;
}
// Logic to find the maxFrequency, minFrequency,
// & count of occurrences of maxFrequency.
int maxFreqValue = INT_MIN;
int minFreqValue = INT_MAX;
int maxFreqCounter = 0;
for (auto& pair : freqMap) {
if (pair.second == maxFreqValue) {
maxFreqCounter++;
}
if (pair.second > maxFreqValue) {
maxFreqValue = pair.second;
maxFreqCounter = 1;
}
if (pair.second < minFreqValue) {
minFreqValue = pair.second;
}
}
// Now using those 3 variables check if the
// given constraints of the problem are satisfied
// or not.
if ((maxFreqValue - minFreqValue) == 0) {
return true;
} else if ((maxFreqValue - minFreqValue) == 1) {
if (maxFreqCounter == 1) {
return true;
} else {
return false;
}
} else {
return false;
}
}
int main() {
// Corner-case input when there exist multiple
// occurrences of maxFrequency characters. In this
// case, it is x and y which are having equal
// frequencies and are maxFrequencies as well.
string str = "xxxyyyzzaa";
if (sameFreq(str)) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
return 0;
}
//This code is conributed by Prachi.
// Java program to check if frequency of all
// characters can become same by one removal
import java.util.HashMap;
public class Solution {
private static boolean sameFreq(String s)
{
HashMap<Character, Integer> freqMap
= new HashMap<>();
// logic to populate the frequency of each
// character.
for (int i = 0; i < s.length(); i++) {
freqMap.put(s.charAt(i),
freqMap.getOrDefault(s.charAt(i), 0)
+ 1);
}
// Logic to find the maxFrequency, minFrequency,
// & count of occurrences of maxFrequency.
int maxFreqValue = Integer.MIN_VALUE;
int minFreqValue = Integer.MAX_VALUE;
int maxFreqCounter = 0;
for (char key : freqMap.keySet()) {
if (freqMap.get(key) == maxFreqValue) {
maxFreqCounter++;
}
if (freqMap.get(key) > maxFreqValue) {
maxFreqValue = freqMap.get(key);
maxFreqCounter = 1;
}
if (freqMap.get(key) < minFreqValue) {
minFreqValue = freqMap.get(key);
}
}
// Now using those 3 variables check if the
// given constraints of the problem are satisfied
// or not.
if ((maxFreqValue - minFreqValue) == 0) {
return true;
}
else if ((maxFreqValue - minFreqValue) == 1) {
if (maxFreqCounter == 1) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
public static void main(String[] args)
{
// corner-case input when there exists multiple
// occurrences of maxFrequency characters. In this
// case, it is x and y which are having equal
// frequencies and are maxFrequencies as well.
String str = "xxxyyyzzaa";
if (sameFreq(str)) {
System.out.println("YES");
}
else {
System.out.println("NO");
}
}
}
// This code is contributed by Nikhil B.
def same_freq(s):
freq_map = {}
# Populate the frequency of each character
for char in s:
freq_map[char] = freq_map.get(char, 0) + 1
# Find the maxFrequency, minFrequency, and count of occurrences of maxFrequency
max_freq_value = float('-inf')
min_freq_value = float('inf')
max_freq_counter = 0
for key in freq_map:
if freq_map[key] == max_freq_value:
max_freq_counter += 1
if freq_map[key] > max_freq_value:
max_freq_value = freq_map[key]
max_freq_counter = 1
if freq_map[key] < min_freq_value:
min_freq_value = freq_map[key]
# Check if the given constraints of the problem are satisfied
if (max_freq_value - min_freq_value) == 0:
return True
elif (max_freq_value - min_freq_value) == 1:
if max_freq_counter == 1:
return True
else:
return False
else:
return False
# Main function
def main():
# Corner-case input when there exist multiple occurrences of maxFrequency characters
str = "xxxyyyzzaa"
if same_freq(str):
print("YES")
else:
print("NO")
# Execute main function
if __name__ == "__main__":
main()
function sameFreq(s) {
let freqMap = new Map();
// logic to populate the frequency of each character.
for (let i = 0; i < s.length; i++) {
freqMap.set(s.charAt(i), (freqMap.get(s.charAt(i)) || 0) + 1);
}
// Logic to find the maxFrequency, minFrequency,
// & count of occurrences of maxFrequency.
let maxFreqValue = -Infinity;
let minFreqValue = Infinity;
let maxFreqCounter = 0;
for (let [key, value] of freqMap) {
if (value === maxFreqValue) {
maxFreqCounter++;
}
if (value > maxFreqValue) {
maxFreqValue = value;
maxFreqCounter = 1;
}
if (value < minFreqValue) {
minFreqValue = value;
}
}
// Now using those 3 variables check if the
// given constraints of the problem are satisfied or not.
if ((maxFreqValue - minFreqValue) === 0) {
return true;
} else if ((maxFreqValue - minFreqValue) === 1) {
if (maxFreqCounter === 1) {
return true;
} else {
return false;
}
} else {
return false;
}
}
// Test case
let str = "xxxyyyzzaa";
if (sameFreq(str)) {
console.log("YES");
} else {
console.log("NO");
}
Output
NO
Time Complexity : O(n). Where, ‘n’ is the size of the input string.
Auxiliary Space : O(26). The HashMap can at max grow up to a size of 26. Hence, it’s a constant space complexity solution.
Check if frequency of all characters can become same by one removal
Given a string that contains lower alphabetic characters, we need to remove at most one character from this string in such a way that frequency of each distinct character becomes the same in the string.
Examples:
Input: str = “xyyz”
Output: Yes
We can remove character ’y’ from above
string to make the frequency of each
character same.Input: str = “xyyzz”
Output: Yes
We can remove character ‘x’ from above
string to make the frequency of each
character same.Input: str = “xxxxyyzz”
Output: No
It is not possible to make frequency of
each character same just by removing at
most one character from above string.
Approach: The problem can be solved using the concept of hashing. The main thing to observe in this problem is that the position of characters does not matter here so we will count the frequency of characters, if all of them are the same then we are done and there is no need to remove any character to make frequency of characters same Otherwise we can iterate over all characters one by one and decrease their frequency by one, if all frequencies become same then we will flag that it is possible to make character frequency same by at most one removal and if frequencies don’t match then we will increase that frequency again and loop for other characters.
Below is a dry run of the above approach:
Below is the implementation of the above approach:
// C++ program to get same frequency character
// string by removal of at most one char
#include <bits/stdc++.h>
using namespace std;
#define M 26
// Utility method to get index of character ch
// in lower alphabet characters
int getIdx(char ch)
{
return (ch - 'a');
}
// Returns true if all non-zero elements
// values are same
bool allSame(int freq[], int N)
{
int same;
// get first non-zero element
int i;
for (i = 0; i < N; i++) {
if (freq[i] > 0) {
same = freq[i];
break;
}
}
// check equality of each element with variable same
for (int j = i + 1; j < N; j++)
if (freq[j] > 0 && freq[j] != same)
return false;
return true;
}
// Returns true if we can make all character
// frequencies same
bool possibleSameCharFreqByOneRemoval(string str)
{
int l = str.length();
// fill frequency array
int freq[M] = { 0 };
for (int i = 0; i < l; i++)
freq[getIdx(str[i])]++;
// if all frequencies are same, then return true
if (allSame(freq, M))
return true;
/* Try decreasing frequency of all character
by one and then check all equality of all
non-zero frequencies */
for (char c = 'a'; c <= 'z'; c++) {
int i = getIdx(c);
// Check character only if it occurs in str
if (freq[i] > 0) {
freq[i]--;
if (allSame(freq, M))
return true;
freq[i]++;
}
}
return false;
}
// Driver code to test above methods
int main()
{
string str = "xyyzz";
if (possibleSameCharFreqByOneRemoval(str))
cout << "Yes";
else
cout << "No";
}
// Java program to get same frequency character
// string by removal of at most one char
public class GFG {
static final int M = 26;
// Utility method to get index of character ch
// in lower alphabet characters
static int getIdx(char ch)
{
return (ch - 'a');
}
// Returns true if all non-zero elements
// values are same
static boolean allSame(int freq[], int N)
{
int same = 0;
// get first non-zero element
int i;
for (i = 0; i < N; i++) {
if (freq[i] > 0) {
same = freq[i];
break;
}
}
// check equality of each element with
// variable same
for (int j = i + 1; j < N; j++)
if (freq[j] > 0 && freq[j] != same)
return false;
return true;
}
// Returns true if we can make all character
// frequencies same
static boolean possibleSameCharFreqByOneRemoval(String str)
{
int l = str.length();
// fill frequency array
int[] freq = new int[M];
for (int i = 0; i < l; i++)
freq[getIdx(str.charAt(i))]++;
// if all frequencies are same, then return true
if (allSame(freq, M))
return true;
/* Try decreasing frequency of all character
by one and then check all equality of all
non-zero frequencies */
for (char c = 'a'; c <= 'z'; c++) {
int i = getIdx(c);
// Check character only if it occurs in str
if (freq[i] > 0) {
freq[i]--;
if (allSame(freq, M))
return true;
freq[i]++;
}
}
return false;
}
// Driver code to test above methods
public static void main(String args[])
{
String str = "xyyzz";
if (possibleSameCharFreqByOneRemoval(str))
System.out.println("Yes");
else
System.out.println("No");
}
}
// This code is contributed by Sumit Ghosh
# Python3 program to get same frequency character
# string by removal of at most one char
M = 26
# Utility method to get index of character ch
# in lower alphabet characters
def getIdx(ch):
return (ord(ch) - ord('a'))
# Returns true if all non-zero elements
# values are same
def allSame(freq, N):
# get first non-zero element
for i in range(0, N):
if(freq[i] > 0):
same = freq[i]
break
# check equality of each element
# with variable same
for j in range(i + 1, N):
if(freq[j] > 0 and freq[j] != same):
return False
return True
# Returns true if we can make all
# character frequencies same
def possibleSameCharFreqByOneRemoval(str1):
l = len(str1)
# fill frequency array
freq = [0] * M
for i in range(0, l):
freq[getIdx(str1[i])] += 1
# if all frequencies are same,
# then return true
if(allSame(freq, M)):
return True
# Try decreasing frequency of all character
# by one and then check all equality of all
# non-zero frequencies
for i in range(0, 26):
# Check character only if it
# occurs in str
if(freq[i] > 0):
freq[i] -= 1
if(allSame(freq, M)):
return True
freq[i] += 1
return False
# Driver code
if __name__ == "__main__":
str1 = "xyyzz"
if(possibleSameCharFreqByOneRemoval(str1)):
print("Yes")
else:
print("No")
# This code is contributed by Sairahul099
// C# program to get same frequency
// character string by removal of
// at most one char
using System;
class GFG {
static int M = 26;
// Utility method to get
// index of character ch
// in lower alphabet characters
static int getIdx(char ch)
{
return (ch - 'a');
}
// Returns true if all
// non-zero elements
// values are same
static bool allSame(int[] freq,
int N)
{
int same = 0;
// get first non-zero element
int i;
for (i = 0; i < N; i++) {
if (freq[i] > 0) {
same = freq[i];
break;
}
}
// check equality of
// each element with
// variable same
for (int j = i + 1; j < N; j++)
if (freq[j] > 0 && freq[j] != same)
return false;
return true;
}
// Returns true if we
// can make all character
// frequencies same
static bool possibleSameCharFreqByOneRemoval(string str)
{
int l = str.Length;
// fill frequency array
int[] freq = new int[M];
for (int i = 0; i < l; i++)
freq[getIdx(str[i])]++;
// if all frequencies are same,
// then return true
if (allSame(freq, M))
return true;
/* Try decreasing frequency of all
character by one and then check
all equality of all non-zero
frequencies */
for (char c = 'a'; c <= 'z'; c++) {
int i = getIdx(c);
// Check character only if
// it occurs in str
if (freq[i] > 0) {
freq[i]--;
if (allSame(freq, M))
return true;
freq[i]++;
}
}
return false;
}
// Driver code
public static void Main()
{
string str = "xyyzz";
if (possibleSameCharFreqByOneRemoval(str))
Console.Write("Yes");
else
Console.Write("No");
}
}
// This code is contributed
// by ChitraNayal
// Utility method to get index of character
// ch in lower alphabet characters
function getIdx(ch)
{
return (ch - 'a');
}
// Returns true if all non-zero elements
// values are same
function allSame(freq, N)
{
let same = 0;
// Get first non-zero element
let i;
for(i = 0; i < N; i++)
{
if (freq[i] > 0)
{
same = freq[i];
break;
}
}
// Check equality of each element with
// variable same
for(let j = i + 1; j < N; j++)
if (freq[j] > 0 && freq[j] != same)
return false;
return true;
}
// Returns true if we can make all character
// frequencies same
function possibleSameCharFreqByOneRemoval(str)
{
let l = str.length;
// Fill frequency array
let freq = new Array(26).fill(0);
for(let i = 0; i < l; i++)
freq[getIdx(str[i])]++;
// If all frequencies are same,
// then return true
if (allSame(freq, 26))
return "Yes";
// Try decreasing frequency of all character
// by one and then check all equality of all
// non-zero frequencies
for(let c = 'a'; c <= 'z'; c++)
{
let i = getIdx(c);
// Check character only if
// it occurs in str
if (freq[i] > 0)
{
freq[i]--;
if (allSame(freq, 26))
return "Yes";
freq[i]++;
}
}
return "No";
}
// Driver code
let str = "xyyzz";
let result = possibleSameCharFreqByOneRemoval(str);
console.log(result);
<?php
// PHP program to get same frequency
// character string by removal of at
// most one char
$M = 26;
// Utility method to get index
// of character ch in lower
// alphabet characters
function getIdx($ch)
{
return ($ch - 'a');
}
// Returns true if all
// non-zero elements
// values are same
function allSame(&$freq, $N)
{
// get first non-zero element
for ($i = 0; $i < $N; $i++)
{
if ($freq[$i] > 0)
{
$same = $freq[$i];
break;
}
}
// check equality of each
// element with variable same
for ($j = $i + 1; $j < $N; $j++)
if ($freq[$j] > 0 &&
$freq[$j] != $same)
return false;
return true;
}
// Returns true if we
// can make all character
// frequencies same
function possibleSameCharFreqByOneRemoval($str)
{
global $M;
$l = strlen($str);
// fill frequency array
$freq = array_fill(0, $M, NULL);
for ($i = 0; $i < $l; $i++)
$freq[getIdx($str[$i])]++;
// if all frequencies are same,
// then return true
if (allSame($freq, $M))
return true;
/* Try decreasing frequency of all
character by one and then check
all equality of all non-zero
frequencies */
for ($c = 'a'; $c <= 'z'; $c++)
{
$i = getIdx($c);
// Check character only
// if it occurs in str
if ($freq[$i] > 0)
{
$freq[$i]--;
if (allSame($freq, $M))
return true;
$freq[$i]++;
}
}
return false;
}
// Driver code
$str = "xyyzz";
if (possibleSameCharFreqByOneRemoval($str))
echo "Yes";
else
echo "No";
// This code is contributed
// by ChitraNayal
?>
Output
Yes
Time Complexity: O(n) assuming alphabet size is constant.
Auxiliary Space: O(1)
Alternate way to solve this problem using Collections framework:
In this approach we are going to use Collection class to solve the given problem.
Steps-by-step algorithm:
- First we will take 2 hashmap. One will used to store character and its count and another will stored the count of occurrence of character and number to character which having same count.
- After this if 2nd hashmap size is 1 that means character frequency is one so we simply return true.
- Now we will declare 2 arraylist to store key in one arraylist and values in another list.
- Now we will check if it is possible to make frequency of character by one removal or not. If yes then return true else return false.
Below is the implementation of the above approach:
#include <bits/stdc++.h>
using namespace std;
bool sameFreq(string s)
{
// create two empty maps for storing character
// frequencies and frequency counts
map<char, int> h;
map<int, int> a;
// iterate through each character in the input string
for (int i = 0; i < s.length(); i++)
{
// increment the count for the current character in
// the frequency map
h[s[i]]++;
}
// iterate through each key-value pair in the frequency
// map
for (auto map : h) {
// increment the count for the current frequency in
// the frequency count map
a[map.second]++;
}
// check if there is only one unique frequency count
if (a.size() == 1) {
return true;
}
// check if there are only two unique frequency counts
else if (a.size() == 2) {
vector<int> list;
vector<int> l;
// iterate through each key-value pair in the
// frequency count map
for (auto entry : a) {
int key = entry.first;
int value = entry.second;
// add the current frequency and frequency count
// to their respective vectors
list.push_back(key);
l.push_back(value);
}
// check if there is a single occurrence of a
// frequency count of 1
if ((list[1] == 1 && l[1] == 1)
|| (list[0] == 1 && l[0] == 1)) {
return true;
}
// check if the difference between the two frequency
// counts is 1
else if (abs(list[1] - list[0]) == 1) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
int main()
{
string str = "xxxyyz";
if (sameFreq(str)) {
cout << "YES" << endl;
}
else {
cout << "NO" << endl;
}
return 0;
}
import java.util.*;
public class HelloWorld {
static public boolean sameFreq(String s) {
HashMap<Character, Integer> h = new HashMap<>();
HashMap<Integer, Integer> a = new HashMap<>();
for(int i = 0; i<s.length(); i++)
{
h.put(s.charAt(i), h.getOrDefault(s.charAt(i), 0)+1);
}
for (Map.Entry<Character, Integer> map : h.entrySet()) {
a.put(map.getValue(), a.getOrDefault(map.getValue(), 0)+1);
}
if(a.size() == 1)
{
return true;
}
if(a.size() == 2)
{
ArrayList<Integer> list = new ArrayList<>();
ArrayList<Integer> l = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : a.entrySet()) {
Integer key = entry.getKey();
Integer value = entry.getValue();
list.add(key);
l.add(value);
}
if((list.get(1) == 1 && l.get(1) == 1) || (list.get(0) == 1 && l.get(0) == 1)) {
return true;
}
else if(Math.abs(list.get(1) - list.get(0)) == 1) {
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
public static void main(String[] args)
{
String str="xxxyyz";
if(sameFreq(str)){
System.out.println("YES");
}else{
System.out.println("NO");
}
}
}
def sameFreq(s):
# create two empty dictionaries for storing character
# frequencies and frequency counts
h = {}
a = {}
# iterate through each character in the input string
for i in s:
# increment the count for the current character in
# the frequency dictionary
h[i] = h.get(i, 0) + 1
# iterate through each key-value pair in the frequency
# dictionary
for key, value in h.items():
# increment the count for the current frequency in
# the frequency count dictionary
a[value] = a.get(value, 0) + 1
# check if there is only one unique frequency count
if len(a) == 1:
return True
# check if there are only two unique frequency counts
elif len(a) == 2:
l = []
list = []
# iterate through each key-value pair in the
# frequency count dictionary
for key, value in a.items():
# add the current frequency and frequency count
# to their respective lists
list.append(key)
l.append(value)
# check if there is a single occurrence of a
# frequency count of 1
if (list[1] == 1 and l[1] == 1) or (list[0] == 1 and l[0] == 1):
return True
# check if the difference between the two frequency
# counts is 1
elif abs(list[1] - list[0]) == 1:
return True
else:
return False
else:
return False
str = "xxxyyz"
if sameFreq(str):
print("YES")
else:
print("NO")
using System;
using System.Collections.Generic;
class Program {
static bool SameFreq(string s)
{
// create two empty dictionaries for storing
// character frequencies and frequency counts
Dictionary<char, int> h
= new Dictionary<char, int>();
Dictionary<int, int> a = new Dictionary<int, int>();
// iterate through each character in the input
// string
foreach(char c in s)
{
// increment the count for the current character
// in the frequency dictionary
if (h.ContainsKey(c)) {
h[c]++;
}
else {
h.Add(c, 1);
}
}
// iterate through each key-value pair in the
// frequency dictionary
foreach(KeyValuePair<char, int> kvp in h)
{
// increment the count for the current frequency
// in the frequency count dictionary
if (a.ContainsKey(kvp.Value)) {
a[kvp.Value]++;
}
else {
a.Add(kvp.Value, 1);
}
}
// check if there is only one unique frequency count
if (a.Count == 1) {
return true;
}
// check if there are only two unique frequency
// counts
else if (a.Count == 2) {
List<int> list = new List<int>();
List<int> l = new List<int>();
// iterate through each key-value pair in the
// frequency count dictionary
foreach(KeyValuePair<int, int> kvp in a)
{
int key = kvp.Key;
int value = kvp.Value;
// add the current frequency and frequency
// count to their respective lists
list.Add(key);
l.Add(value);
}
// check if there is a single occurrence of a
// frequency count of 1
if ((list[1] == 1 && l[1] == 1)
|| (list[0] == 1 && l[0] == 1)) {
return true;
}
// check if the difference between the two
// frequency counts is 1
else if (Math.Abs(list[1] - list[0]) == 1) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
static void Main(string[] args)
{
string str = "xxxyyz";
if (SameFreq(str)) {
Console.WriteLine("YES");
}
else {
Console.WriteLine("NO");
}
}
}
// This code is contributed by Prajwal Kandekar
function sameFreq(s) {
// create two empty maps for storing character
// frequencies and frequency counts
let h = new Map();
let a = new Map();
// iterate through each character in the input string
for (let i = 0; i < s.length; i++) {
// increment the count for the current character in
// the frequency map
h.set(s[i], (h.get(s[i]) || 0) + 1);
}
// iterate through each key-value pair in the frequency
// map
for (let [key, value] of h) {
// increment the count for the current frequency in
// the frequency count map
a.set(value, (a.get(value) || 0) + 1);
}
// check if there is only one unique frequency count
if (a.size === 1) {
return true;
}
// check if there are only two unique frequency counts
else if (a.size === 2) {
let list = [];
let l = [];
// iterate through each key-value pair in the
// frequency count map
for (let [key, value] of a) {
// add the current frequency and frequency count
// to their respective vectors
list.push(key);
l.push(value);
}
// check if there is a single occurrence of a
// frequency count of 1
if ((list[1] === 1 && l[1] === 1)
|| (list[0] === 1 && l[0] === 1)) {
return true;
}
// check if the difference between the two frequency
// counts is 1
else if (Math.abs(list[1] - list[0]) === 1) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
let str = "xxxyyz";
if (sameFreq(str)) {
console.log("YES");
}
else {
console.log("NO");
}
Output
NO
Time Complexity: O(n), where n is the size of the string
Auxiliary Space: O(26 + 26), extra space used by both the HashMaps.