LeetCode 2840 – Check if Strings Can be Made Equal With Operations II
Check if Strings Can be Made Equal
With Operations II
(i, n-1-i) — that's
LeetCode 2839 (Operations I). This problem allows swapping any two indices
i, j where j − i is even, which is a fundamentally different (and simpler) rule.
Problem Statement
You are given two strings s1 and s2, both of length n. An operation consists of choosing any two indices i and j such that i < j and j − i is even, then swapping s1[i] and s1[j].
You may perform this operation any number of times. Return true if you can make s1 equal to s2, otherwise return false.
1 ≤ n ≤ 10⁵, strings consist of lowercase English letters only.Intuition & Key Insight
The rule j − i is even means only indices of the same parity can be swapped. Think about why: if both i and j are even, their difference is even. If both are odd, their difference is also even. You can never swap an even index with an odd index.
This divides the string into two independent pools:
- Even pool — characters at indices 0, 2, 4, … can be freely rearranged among themselves.
- Odd pool — characters at indices 1, 3, 5, … can be freely rearranged among themselves.
s1 and s2 have identical character frequencies at even positions? And identical frequencies at odd positions? If yes → true.Here is the parity split for the test case s1="abcdba", s2="cabdab":
Step-by-Step Frequency Trace
We walk both strings together with a step of 2, incrementing for s1 and decrementing for s2. At the end every count must be zero.
Java Solution — O(n) / O(1)
import java.util.Arrays; class Solution { public boolean checkStrings(String s1, String s2) { // Check even-indexed characters, then odd-indexed characters return check(s1, s2, 0) && check(s1, s2, 1); } private boolean check(String s1, String s2, int start) { int[] freq = new int[26]; // Step by 2 so we stay on the same parity for (int i = start; i < s1.length(); i += 2) { freq[s1.charAt(i) - 'a']++; // count up for s1 freq[s2.charAt(i) - 'a']--; // count down for s2 } // Every frequency must cancel to zero for (int count : freq) { if (count != 0) return false; } return true; } }
int[26] array is always fixed-size regardless of n, so space is truly O(1). We do exactly one pass per parity group, giving O(n) total.Alternative Approaches
| Approach | Time | Space | Notes |
|---|---|---|---|
| Frequency array (optimal) | O(n) | O(1) | Single pass, int[26] — best for interviews |
| Sort parity sub-arrays | O(n log n) | O(n) | Extract even/odd chars, sort, compare. Clean but allocates |
| HashMap per parity | O(n) | O(n) | Readable, but boxing/hashing overhead vs int[] |
| XOR trick (chars only) | O(n) | O(1) | Necessary but not sufficient — XOR match ≠ multiset match |
| Brute-force simulation | O(2^(n/2)) | O(n) | Correct but exponential — only for tiny inputs / testing |
class Solution { public boolean checkStrings(String s1, String s2) { return sortedParity(s1, 0).equals(sortedParity(s2, 0)) && sortedParity(s1, 1).equals(sortedParity(s2, 1)); } private String sortedParity(String s, int start) { char[] chars = new char[(s.length() - start + 1) / 2]; for (int i = start, j = 0; i < s.length(); i += 2) chars[j++] = s.charAt(i); Arrays.sort(chars); return new String(chars); } }
Common Mistakes to Avoid
{s1[i], s1[n-1-i]} equals {s2[i], s2[n-1-i]} is the solution to problem 2839, not 2840. The allowed swap set here is much larger.s1_even_xor == s2_even_xor is a necessary but not sufficient condition. The strings "aab" and "bba" have the same XOR but different multisets at even positions.n/2 for even n, or ⌊n/2⌋ for odd n) naturally ends up in the even pool. The algorithm handles it correctly with no special case needed.HashMap<Character, Integer>. The alphabet is fixed at 26 — an int[26] is O(1) space and cache-friendly.