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.
You are given two strings s1 and s2 of equal length. A string swap is an operation where you choose two indices in a string (not necessarily different) and swap the characters at these indices.
Return true if it is possible to make both strings equal by performing at most one string swap on exactly one of the strings. Otherwise, return false.
Example 1:
Input: s1 = "bank", s2 = "kanb" Output: true Explanation: For example, swap the first character with the last character of s2 to make "bank".
Example 2:
Input: s1 = "attack", s2 = "defend" Output: false Explanation: It is impossible to make them equal with one string swap.
Example 3:
Input: s1 = "kelb", s2 = "kelb" Output: true Explanation: The two strings are already equal, so no string swap operation is required.
Constraints:
1 <= s1.length, s2.length <= 100s1.length == s2.lengths1 and s2 consist of only lowercase English letters.Problem summary: You are given two strings s1 and s2 of equal length. A string swap is an operation where you choose two indices in a string (not necessarily different) and swap the characters at these indices. Return true if it is possible to make both strings equal by performing at most one string swap on exactly one of the strings. Otherwise, return false.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map
"bank" "kanb"
"attack" "defend"
"kelb" "kelb"
buddy-strings)make-number-of-distinct-characters-equal)count-almost-equal-pairs-i)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1790: Check if One String Swap Can Make Strings Equal
class Solution {
public boolean areAlmostEqual(String s1, String s2) {
int cnt = 0;
char c1 = 0, c2 = 0;
for (int i = 0; i < s1.length(); ++i) {
char a = s1.charAt(i), b = s2.charAt(i);
if (a != b) {
if (++cnt > 2 || (cnt == 2 && (a != c2 || b != c1))) {
return false;
}
c1 = a;
c2 = b;
}
}
return cnt != 1;
}
}
// Accepted solution for LeetCode #1790: Check if One String Swap Can Make Strings Equal
func areAlmostEqual(s1 string, s2 string) bool {
cnt := 0
var c1, c2 byte
for i := range s1 {
a, b := s1[i], s2[i]
if a != b {
cnt++
if cnt > 2 || (cnt == 2 && (a != c2 || b != c1)) {
return false
}
c1, c2 = a, b
}
}
return cnt != 1
}
# Accepted solution for LeetCode #1790: Check if One String Swap Can Make Strings Equal
class Solution:
def areAlmostEqual(self, s1: str, s2: str) -> bool:
cnt = 0
c1 = c2 = None
for a, b in zip(s1, s2):
if a != b:
cnt += 1
if cnt > 2 or (cnt == 2 and (a != c2 or b != c1)):
return False
c1, c2 = a, b
return cnt != 1
// Accepted solution for LeetCode #1790: Check if One String Swap Can Make Strings Equal
impl Solution {
pub fn are_almost_equal(s1: String, s2: String) -> bool {
if s1 == s2 {
return true;
}
let (s1, s2) = (s1.as_bytes(), s2.as_bytes());
let mut idxs = vec![];
for i in 0..s1.len() {
if s1[i] != s2[i] {
idxs.push(i);
}
}
if idxs.len() != 2 {
return false;
}
s1[idxs[0]] == s2[idxs[1]] && s2[idxs[0]] == s1[idxs[1]]
}
}
// Accepted solution for LeetCode #1790: Check if One String Swap Can Make Strings Equal
function areAlmostEqual(s1: string, s2: string): boolean {
let c1, c2;
let cnt = 0;
for (let i = 0; i < s1.length; ++i) {
const a = s1.charAt(i);
const b = s2.charAt(i);
if (a != b) {
if (++cnt > 2 || (cnt == 2 && (a != c2 || b != c1))) {
return false;
}
c1 = a;
c2 = b;
}
}
return cnt != 1;
}
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.