Given two strings s1 and s2 of equal length, determine if you can make s1 equal to s2 by swapping exactly one pair of characters in s1.
s1 and swap the characters at those positions.s1 == s2 already).true if it's possible to make s1 equal to s2 with at most one swap, otherwise return false.1 <= s1.length, s2.length <= 100, s1.length == s2.length, s1 and s2 consist of lowercase English letters.
The naive approach would be to try every possible pair of indices in s1, swap them, and check if the result matches s2. However, this is inefficient, especially for long strings.
Let's reason about the problem:
s1 is already equal to s2, then no swaps are needed. But, we need to check if a swap is allowed (since the problem says "at most one swap", not "exactly one").s1 and s2 differ. If there are more than 2 differences, one swap can't fix all of them.s1 might make it equal to s2. We need to check that the characters at those positions are "crossed" between the two strings.We can solve this problem in a few clear steps:
s1 is already equal to s2, return true. (Swapping is optional.)
s1 and s2 differ, check if swapping these two characters in s1 makes the strings equal.true (no swap needed).false (impossible with one swap).i and j, check that s1[i] == s2[j] and s1[j] == s2[i].
This approach is efficient because we only need to scan the strings once, and all operations are constant time after that.
Let's consider the example: s1 = "bank", s2 = "kanb".
s1[0] and s1[3] makes s1 equal to s2:
s1 becomes "kanb", which is exactly s2.true.
Another example: s1 = "attack", s2 = "defend".
false.The key insight is that only two mismatches can be fixed with a single swap, and we can find those mismatches efficiently by a single scan. This approach is both simple and optimal, avoiding unnecessary swaps or brute-force checks. By focusing on the positions where the strings differ, we can quickly determine if a one-swap transformation is possible.
class Solution:
def areAlmostEqual(self, s1: str, s2: str) -> bool:
if s1 == s2:
return True
diff = []
for i in range(len(s1)):
if s1[i] != s2[i]:
diff.append(i)
if len(diff) > 2:
return False
if len(diff) != 2:
return False
i, j = diff
return s1[i] == s2[j] and s1[j] == s2[i]
class Solution {
public:
bool areAlmostEqual(string s1, string s2) {
if (s1 == s2) return true;
vector<int> diff;
for (int i = 0; i < s1.size(); ++i) {
if (s1[i] != s2[i])
diff.push_back(i);
if (diff.size() > 2)
return false;
}
if (diff.size() != 2)
return false;
int i = diff[0], j = diff[1];
return s1[i] == s2[j] && s1[j] == s2[i];
}
};
class Solution {
public boolean areAlmostEqual(String s1, String s2) {
if (s1.equals(s2)) return true;
List<Integer> diff = new ArrayList<>();
for (int i = 0; i < s1.length(); i++) {
if (s1.charAt(i) != s2.charAt(i))
diff.add(i);
if (diff.size() > 2)
return false;
}
if (diff.size() != 2)
return false;
int i = diff.get(0), j = diff.get(1);
return s1.charAt(i) == s2.charAt(j) && s1.charAt(j) == s2.charAt(i);
}
}
var areAlmostEqual = function(s1, s2) {
if (s1 === s2) return true;
let diff = [];
for (let i = 0; i < s1.length; i++) {
if (s1[i] !== s2[i])
diff.push(i);
if (diff.length > 2)
return false;
}
if (diff.length !== 2)
return false;
let [i, j] = diff;
return s1[i] === s2[j] && s1[j] === s2[i];
};