LeetCode 2839 - Check if Strings Can be Made Equal With Operations I
Problem Statement
You are given two strings s1 and s2, both of length 4, consisting of lowercase English letters.
You can apply the following operation on any of the two strings any number of times:
j - i = 2, then swap the two characters at those indices.
Return true if you can make the strings equal, and false otherwise.
s1.length == s2.length == 4s1ands2consist only of lowercase English letters
Intuition
The key constraint is j - i = 2. In a length-4 string that means only two possible swaps exist:
Characters at even positions (0,2) can only ever swap with each other. Same for odd positions (1,3).
Initial state
Swap s1[0] ↔ s1[2] "abcd" → "cbad"
s1[0] = 'c' now matches s2[0] ✓
Swap s1[1] ↔ s1[3] "cbad" → "cdab"
All positions match s2 → return true ✓
Approach & Algorithm
{0, 2} form one independent group and odd indices {1, 3} form another. Each group can only be in 2 possible states — original order or swapped.
Check the even group {0, 2}
Do s1[0]==s2[0] && s1[2]==s2[2] (no swap needed) OR s1[0]==s2[2] && s1[2]==s2[0] (one swap needed)?
Check the odd group {1, 3}
Do s1[1]==s2[1] && s1[3]==s2[3] (no swap needed) OR s1[1]==s2[3] && s1[3]==s2[1] (one swap needed)?
Return the AND of both checks
Both groups must independently satisfy their condition. One failure means the strings can never be made equal.
Java Solution
class Solution { public boolean canBeEqual(String s1, String s2) { // ── Even group: positions 0 and 2 ── // Either already equal, or they can swap with each other boolean evenMatch = (s1.charAt(0) == s2.charAt(0) && s1.charAt(2) == s2.charAt(2)) || (s1.charAt(0) == s2.charAt(2) && s1.charAt(2) == s2.charAt(0)); // ── Odd group: positions 1 and 3 ── // Either already equal, or they can swap with each other boolean oddMatch = (s1.charAt(1) == s2.charAt(1) && s1.charAt(3) == s2.charAt(3)) || (s1.charAt(1) == s2.charAt(3) && s1.charAt(3) == s2.charAt(1)); return evenMatch && oddMatch; } }
class Solution { public boolean canBeEqual(String s1, String s2) { // Extract and sort each group — if sorted arrays match, // some permutation (via swaps) can make them equal char[] e1 = {s1.charAt(0), s1.charAt(2)}; char[] e2 = {s2.charAt(0), s2.charAt(2)}; char[] o1 = {s1.charAt(1), s1.charAt(3)}; char[] o2 = {s2.charAt(1), s2.charAt(3)}; Arrays.sort(e1); Arrays.sort(e2); Arrays.sort(o1); Arrays.sort(o2); return Arrays.equals(e1, e2) && Arrays.equals(o1, o2); } }
class Solution: def canBeEqual(self, s1: str, s2: str) -> bool: # sorted even group of s1 must match that of s2 # same for odd group return ( sorted([s1[0], s1[2]]) == sorted([s2[0], s2[2]]) and sorted([s1[1], s1[3]]) == sorted([s2[1], s2[3]]) )
Complexity Analysis
| Approach | Time | Space | Notes |
|---|---|---|---|
| Direct Comparison | O(1) | O(1) | 4 char comparisons, zero allocations |
| Sort Groups | O(1) | O(1)* | Allocates 4 char arrays — technically O(1) due to fixed size |
| HashMap frequency | O(1) | O(1)* | Overkill — HashMap overhead for 2-element comparison |
| Brute force permutations | O(1) | O(1) | Only 4 combos to check — works but verbose |
All Approaches — Pros & Cons
Direct Index Comparison Recommended
Compare even-group pairs directly with two boolean expressions, AND the results together.
✓ Zero allocations. Fastest possible. O(1) time and O(1) space. Reads exactly like the problem statement.
✗ Slightly verbose for larger string sizes (doesn't generalize beyond length 4 without modification).
Sort the Groups
Extract indices 0,2 and 1,3 from both strings into char arrays, sort and compare with Arrays.equals().
✓ Clean and easy to generalize to longer strings. Very readable for interviews.
✗ Allocates 4 temporary arrays. Arrays.sort on 2-element arrays is still function-call overhead vs direct comparison.
Brute Force — Try All Combinations
Generate all 4 possible combinations (even swapped/not × odd swapped/not) and check if any equals s2.
✓ Extremely easy to reason about and verify for correctness. No edge-case thinking needed.
✗ Verbose, creates temporary strings, hard to scale. Wastes computation covering already-equivalent logical paths.
HashMap / Frequency Count
Build frequency maps for characters at even positions in s1 vs s2, and same for odd positions; compare both maps.
✓ Scales well if string length grows or if the problem allowed more complex swaps across multiple positions.
✗ Massive overkill for this problem. HashMap object creation and hashing for 2-char comparison is ~100× heavier than a direct boolean check.