Check Whether Two Strings are Almost Equivalent solution and explanation
9 more videos on this problem
Check whether two Strings are almost equivalent| LeetCode problem 2068Technosage · 9:29 · 7K views
2068. Check Whether Two Strings are Almost Equivalent (Leetcode Easy)Programming Live with Larry · 3:30 · 2K views
2068 Check Whether Two Strings are Almost EquivalentMath Geeks · 1:46 · 429 views
2068. Check Whether Two Strings are Almost Equivalent with python | Leetcode with Python #leetcodeArsalan Ahmed · 9:07 · 381 views
2068. Check Whether Two Strings are Almost Equivalent - Javascript - Time O(n) Space O(n) - LeetcodeAaron Sadino Coding · 12:11 · 184 views
Leetcode | Easy | 2068. Check Whether Two Strings are Almost Equivalent | Hash Table | JavascriptSoftware Interviews Prep · 10:01 · 101 views
LeetCode 2068. Check Whether Two Strings are Almost EquivalentYuki Kitayama · 15:55 · 89 views
Day 749: LeetCode Problem 2068. Check Whether Two Strings are Almost Equivalent - SwiftiOSxBank · 9:52 · 20 views
2068. Check Whether Two Strings are Almost Equivalent: leetcode solution in KotlinPhyo Thinzar Aung · 9:42 · 13 views
Leetcode 2068 Check Whether Two Strings are Almost Equivalent - In Hindi ExplanationAlgorithmicIQ · 11:20 · 13 views
The problem
Two strings word1 and word2 are considered almost equivalent if the differences between the frequencies of each letter from 'a' to 'z' between word1 and word2 is at most 3.
Given two strings word1 and word2, each of length n, return true if word1 and word2 are almost equivalent, or false otherwise.
The frequency of a letter x is the number of times it occurs in the string.
Example 1:
Input: word1 = "aaaa", word2 = "bccb" Output: false Explanation: There are 4 'a's in "aaaa" but 0 'a's in "bccb". The difference is 4, which is more than the allowed 3.
Example 2:
Input: word1 = "abcdeef", word2 = "abaaacc" Output: true Explanation: The differences between the frequencies of each letter in word1 and word2 are at most 3: - 'a' appears 1 time in word1 and 4 times in word2. The difference is 3. - 'b' appears 1 time in word1 and 1 time in word2. The difference is 0. - 'c' appears 1 time in word1 and 2 times in word2. The difference is 1. - 'd' appears 1 time in word1 and 0 times in word2. The difference is 1. - 'e' appears 2 times in word1 and 0 times in word2. The difference is 2. - 'f' appears 1 time in word1 and 0 times in word2. The difference is 1.
Example 3:
Input: word1 = "cccddabba", word2 = "babababab" Output: true Explanation: The differences between the frequencies of each letter in word1 and word2 are at most 3: - 'a' appears 2 times in word1 and 4 times in word2. The difference is 2. - 'b' appears 2 times in word1 and 5 times in word2. The difference is 3. - 'c' appears 3 times in word1 and 0 times in word2. The difference is 3. - 'd' appears 2 times in word1 and 0 times in word2. The difference is 2.
Constraints:
n == word1.length == word2.length1 <= n <= 100word1andword2consist only of lowercase English letters.
Approach overview
Problem Overview: You receive two equal-length strings word1 and word2. The task is to check whether the difference in frequency of every lowercase letter between the two strings is at most 3. If any character appears more than 3 times more in one string than the other, the strings are not almost equivalent.
The key observation: the exact positions of characters do not matter. Only the frequency of each letter matters. That immediately points toward a hash table or frequency counting solution.
Approach 1: Frequency Counting with Arrays (O(n) time, O(1) space)
Use two fixed-size arrays of length 26 to store counts of each lowercase letter. Iterate through both strings once and increment the appropriate index (c - 'a') for each character. After building the frequency arrays, iterate from 0..25 and compute the absolute difference for each letter. If any difference exceeds 3, return false. Otherwise the strings are almost equivalent.
This works because the alphabet size is constant. The comparison step always checks 26 entries regardless of input length, so the space remains constant. This approach is usually the fastest in practice and avoids hashing overhead.
Approach 2: Using HashMaps (O(n) time, O(k) space)
Store character frequencies using a HashMap for each string. Traverse word1 and word2, updating counts for each character. Then iterate through all lowercase letters or the union of keys in both maps. Compute the absolute difference between the counts from the two maps. If any difference is greater than 3, return false.
This approach is more flexible when the character set is not limited to lowercase letters. Hash maps automatically expand for any character set, making the solution adaptable beyond the typical string problems restricted to 26 letters. The tradeoff is slightly higher constant overhead compared to arrays.
Both methods rely on the same idea: compare per-character frequency differences using a simple counting technique. The difference threshold (3) becomes a straightforward validation step after computing counts.
Recommended for interviews: The array-based frequency counting approach. Interviewers expect candidates to recognize that lowercase letters allow a fixed-size counting array. It runs in O(n) time and O(1) space and demonstrates strong understanding of character frequency techniques. Mentioning the HashMap variant shows awareness of how the solution generalizes when the alphabet size is not fixed.
Approach 1: Frequency Counting with Arrays
This approach utilizes arrays to count the frequency of each letter from 'a' to 'z' for both strings. By iterating through the characters of each word, we can populate two frequency arrays. Then, by comparing the absolute differences between corresponding elements of these arrays, we can determine if the words are almost equivalent.
def are_almost_equivalent(word1, word2):
freq1 = [0] * 26
freq2 = [0] * 26
for ch1, ch2 in zip(word1, word2):
freq1[ord(ch1) - ord('a')] += 1
freq2[ord(ch2) - ord('a')] += 1
return all(abs(f1 - f2) <= 3 for f1, f2 in zip(freq1, freq2))
word1 = "abcdeef"
word2 = "abaaacc"
print(are_almost_equivalent(word1, word2))public class Solution {
public boolean areAlmostEquivalent(String word1, String word2) {
int[] freq1 = new int[26];
int[] freq2 = new int[26];
int n = word1.length();
for (int i = 0; i < n; i++) {
freq1[word1.charAt(i) - 'a']++;
freq2[word2.charAt(i) - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (Math.abs(freq1[i] - freq2[i]) > 3) {
return false;
}
}
return true;
}
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.areAlmostEquivalent("abcdeef", "abaaacc"));
}
}#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool areAlmostEquivalent(string word1, string word2) {
vector<int> freq1(26, 0), freq2(26, 0);
int n = word1.length();
for (int i = 0; i < n; i++) {
freq1[word1[i] - 'a']++;
freq2[word2[i] - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (abs(freq1[i] - freq2[i]) > 3)
return false;
}
return true;
}
int main() {
string word1 = "abcdeef";
string word2 = "abaaacc";
cout << (areAlmostEquivalent(word1, word2) ? "true" : "false") << endl;
return 0;
}function areAlmostEquivalent(word1, word2) {
const freq1 = Array(26).fill(0);
const freq2 = Array(26).fill(0);
for (let i = 0; i < word1.length; i++) {
freq1[word1.charCodeAt(i) - 97]++;
freq2[word2.charCodeAt(i) - 97]++;
}
for (let i = 0; i < 26; i++) {
if (Math.abs(freq1[i] - freq2[i]) > 3) {
return false;
}
}
return true;
}
console.log(areAlmostEquivalent("abcdeef", "abaaacc"));#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
bool areAlmostEquivalent(char *word1, char *word2) {
int freq1[26] = {0};
int freq2[26] = {0};
int n = strlen(word1);
for (int i = 0; i < n; i++) {
freq1[word1[i] - 'a']++;
freq2[word2[i] - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (abs(freq1[i] - freq2[i]) > 3) {
return false;
}
}
return true;
}
int main() {
char *word1 = "abcdeef";
char *word2 = "abaaacc";
printf("%s\n", areAlmostEquivalent(word1, word2) ? "true" : "false");
return 0;
}using System;
public class Solution {
public bool AreAlmostEquivalent(string word1, string word2) {
int[] freq1 = new int[26];
int[] freq2 = new int[26];
for (int i = 0; i < word1.Length; i++) {
freq1[word1[i] - 'a']++;
freq2[word2[i] - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (Math.Abs(freq1[i] - freq2[i]) > 3) {
return false;
}
}
return true;
}
public static void Main() {
Solution sol = new Solution();
Console.WriteLine(sol.AreAlmostEquivalent("abcdeef", "abaaacc"));
}
}The Python solution utilizes lists to count letter frequencies, zipped with characters from each word. The method checks whether the maximum frequency difference does not exceed 3.
Time Complexity: O(n + 26), reducing to O(n) due to the fixed-size letter count.
Space Complexity: O(1) since the frequency lists are constant and limited to 26 elements.
Approach 2: Using HashMaps
This alternate approach uses the hashmap or hash table data structure to record character frequencies for both strings. Hash maps are dynamic, allowing insertion without specifying a fixed field size. The hash maps' keys are characters, and their values are frequencies. The function calculates differences between frequency keys of two maps.
def are_almost_equivalent(word1, word2):
from collections import defaultdict
freq1, freq2 = defaultdict(int), defaultdict(int)
for ch in word1:
freq1[ch] += 1
for ch in word2:
freq2[ch] += 1
for ch in 'abcdefghijklmnopqrstuvwxyz':
if abs(freq1[ch] - freq2[ch]) > 3:
return False
return True
print(are_almost_equivalent("abcdeef", "abaaacc"))import java.util.HashMap;
public class Solution {
public boolean areAlmostEquivalent(String word1, String word2) {
HashMap<Character, Integer> freq1 = new HashMap<>();
HashMap<Character, Integer> freq2 = new HashMap<>();
for (char c : word1.toCharArray())
freq1.put(c, freq1.getOrDefault(c, 0) + 1);
for (char c : word2.toCharArray())
freq2.put(c, freq2.getOrDefault(c, 0) + 1);
for (char c = 'a'; c <= 'z'; c++) {
int count1 = freq1.getOrDefault(c, 0);
int count2 = freq2.getOrDefault(c, 0);
if (Math.abs(count1 - count2) > 3) {
return false;
}
}
return true;
}
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.areAlmostEquivalent("abcdeef", "abaaacc"));
}
}#include <iostream>
#include <unordered_map>
#include <string>
#include <cmath>
using namespace std;
bool areAlmostEquivalent(string word1, string word2) {
unordered_map<char, int> freq1, freq2;
for (char ch : word1) freq1[ch]++;
for (char ch : word2) freq2[ch]++;
for (char ch = 'a'; ch <= 'z'; ch++) {
if (abs(freq1[ch] - freq2[ch]) > 3) {
return false;
}
}
return true;
}
int main() {
cout << areAlmostEquivalent("abcdeef", "abaaacc") << endl; // Output: 1 (true)
return 0;
}function areAlmostEquivalent(word1, word2) {
const freq1 = new Map();
const freq2 = new Map();
for (const char of word1) {
freq1.set(char, (freq1.get(char) || 0) + 1);
}
for (const char of word2) {
freq2.set(char, (freq2.get(char) || 0) + 1);
}
for (let i = 0; i < 26; i++) {
const char = String.fromCharCode(97 + i);
const f1 = freq1.get(char) || 0;
const f2 = freq2.get(char) || 0;
if (Math.abs(f1 - f2) > 3) {
return false;
}
}
return true;
}
console.log(areAlmostEquivalent("abcdeef", "abaaacc"));Using Python's defaultdict, this solution accumulates frequencies of each character in two dictionaries. It defaults to integers unlike regular dictionaries requiring initialization. The condition for 'almost equivalence' checks frequency differences not surpassing 3.
Time Complexity: O(n), with n being the length of the input.
Space Complexity: O(1), considering the 26 distinct possible keys.
Approach 3: Counting
We can create an array cnt of length 26 to record the difference in the number of times each letter appears in the two strings. Then we traverse cnt, if any letter appears the difference in the number of times greater than 3, then return false, otherwise return true.
The time complexity is O(n) and the space complexity is O(C). Where n is the length of the string, and C is the size of the character set, and in this question C = 26.
function checkAlmostEquivalent(word1: string, word2: string): boolean {
const cnt: number[] = new Array(26).fill(0);
for (const c of word1) {
++cnt[c.charCodeAt(0) - 97];
}
for (const c of word2) {
--cnt[c.charCodeAt(0) - 97];
}
return cnt.every(x => Math.abs(x) <= 3);
}func checkAlmostEquivalent(word1 string, word2 string) bool {
cnt := [26]int{}
for _, c := range word1 {
cnt[c-'a']++
}
for _, c := range word2 {
cnt[c-'a']--
}
for _, x := range cnt {
if x > 3 || x < -3 {
return false
}
}
return true
}class Solution {
/**
* @param String $word1
* @param String $word2
* @return Boolean
*/
function checkAlmostEquivalent($word1, $word2) {
for ($i = 0; $i < strlen($word1); $i++) {
$hashtable[$word1[$i]] += 1;
$hashtable[$word2[$i]] -= 1;
}
$keys = array_keys($hashtable);
for ($j = 0; $j < count($keys); $j++) {
if (abs($hashtable[$keys[$j]]) > 3) {
return false;
}
}
return true;
}
}Complexity comparison
| Approach | Complexity |
|---|---|
| Frequency Counting with Arrays | Time Complexity: O(n + 26), reducing to O(n) due to the fixed-size letter count. |
| Using HashMaps | Time Complexity: O(n), with n being the length of the input. |
| Counting | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Frequency Counting with Arrays | O(n) | O(1) | Best when the character set is fixed (lowercase letters). Fastest and most memory-efficient. |
| Using HashMaps | O(n) | O(k) | Useful when characters are not limited to 26 letters or when handling arbitrary Unicode strings. |
Frequently asked questions
Is Check Whether Two Strings are Almost Equivalent easy or hard?
The problem is classified as Easy. It mainly tests basic string traversal and frequency counting, a common pattern in hash table and counting problems.
Check Whether Two Strings are Almost Equivalent Python/Java solution
In Python or Java, iterate through both strings and store character counts using either an array of size 26 or a HashMap. After counting, check that the absolute difference between corresponding frequencies does not exceed 3.
How to solve Check Whether Two Strings are Almost Equivalent in O(n)?
Traverse both strings and maintain frequency counts for each letter. After counting, iterate through all 26 letters and compute the absolute difference between the two counts. If any difference is greater than 3, the strings are not almost equivalent.
What is the best approach for Check Whether Two Strings are Almost Equivalent?
The best approach uses a frequency counting array of size 26. Count the occurrences of each lowercase letter in both strings and compare their absolute differences. If any difference exceeds 3, return false. This runs in O(n) time with O(1) space.
Is Check Whether Two Strings are Almost Equivalent asked at Google/Amazon/Meta?
String frequency and hash table problems like this commonly appear in interviews at companies such as Amazon, Google, and Meta. The question tests understanding of counting techniques and efficient string processing.
What data structure is used in Check Whether Two Strings are Almost Equivalent?
The problem is typically solved using a fixed-size frequency array or a hash map. Arrays are preferred when the character set is limited to lowercase letters, while hash maps handle more general character sets.
What is the time complexity of Check Whether Two Strings are Almost Equivalent?
The optimal solution runs in O(n) time where n is the length of the strings. Each character is processed once to build frequency counts, followed by a constant 26-character comparison step.
