Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Build confidence with an intuition-first walkthrough focused on hash map fundamentals.
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 <= 100word1 and word2 consist only of lowercase English letters.Problem summary: 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.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map
"aaaa" "bccb"
"abcdeef" "abaaacc"
"cccddabba" "babababab"
find-the-occurrence-of-first-almost-equal-substring)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #2068: Check Whether Two Strings are Almost Equivalent
class Solution {
public boolean checkAlmostEquivalent(String word1, String word2) {
int[] cnt = new int[26];
for (int i = 0; i < word1.length(); ++i) {
++cnt[word1.charAt(i) - 'a'];
}
for (int i = 0; i < word2.length(); ++i) {
--cnt[word2.charAt(i) - 'a'];
}
for (int x : cnt) {
if (Math.abs(x) > 3) {
return false;
}
}
return true;
}
}
// Accepted solution for LeetCode #2068: Check Whether Two Strings are Almost Equivalent
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
}
# Accepted solution for LeetCode #2068: Check Whether Two Strings are Almost Equivalent
class Solution:
def checkAlmostEquivalent(self, word1: str, word2: str) -> bool:
cnt = Counter(word1)
for c in word2:
cnt[c] -= 1
return all(abs(x) <= 3 for x in cnt.values())
// Accepted solution for LeetCode #2068: Check Whether Two Strings are Almost Equivalent
struct Solution;
use std::collections::HashMap;
impl Solution {
fn check_almost_equivalent(word1: String, word2: String) -> bool {
let mut hm1: HashMap<char, i32> = HashMap::new();
let mut hm2: HashMap<char, i32> = HashMap::new();
for c in word1.chars() {
*hm1.entry(c).or_default() += 1;
}
for c in word2.chars() {
*hm2.entry(c).or_default() += 1;
}
for c in 'a'..='z' {
let x1 = *hm1.entry(c).or_default();
let x2 = *hm2.entry(c).or_default();
if (x1 - x2).abs() > 3 {
return false;
}
}
true
}
}
#[test]
fn test() {
let word1 = "aaaa".to_string();
let word2 = "bccb".to_string();
let res = false;
assert_eq!(Solution::check_almost_equivalent(word1, word2), res);
let word1 = "abcdeef".to_string();
let word2 = "abaaacc".to_string();
let res = true;
assert_eq!(Solution::check_almost_equivalent(word1, word2), res);
let word1 = "cccddabba".to_string();
let word2 = "babababab".to_string();
let res = true;
assert_eq!(Solution::check_almost_equivalent(word1, word2), res);
}
// Accepted solution for LeetCode #2068: Check Whether Two Strings are Almost Equivalent
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);
}
Use this to step through a reusable interview workflow for this problem.
For each element, scan the rest of the array looking for a match. Two nested loops give n × (n−1)/2 comparisons = O(n²). No extra space since we only use loop indices.
One pass through the input, performing O(1) hash map lookups and insertions at each step. The hash map may store up to n entries in the worst case. This is the classic space-for-time tradeoff: O(n) extra memory eliminates an inner loop.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.