LeetCode 2839: Check if Strings Can be Made Equal With Operations I (Parity Position Invariant)
LeetCode 2839StringInvariantToday we solve LeetCode 2839 - Check if Strings Can be Made Equal With Operations I. The operation only swaps indices (0,2) and (1,3), so index parity is the key invariant.
Source: https://leetcode.com/problems/check-if-strings-can-be-made-equal-with-operations-i/
English
Problem Summary
Given two strings s1 and s2 of length 4, you may repeatedly swap s1[0] with s1[2] and swap s1[1] with s1[3]. Determine whether s1 can become s2.
Key Insight
Indices split into two independent groups: even positions {0,2} and odd positions {1,3}. Allowed operations never move a character from even to odd (or vice versa). Therefore, each parity group's multiset must match between s1 and s2.
Optimal Algorithm
Sort the two-character strings from even positions and odd positions separately, then compare.
sort(s1[0], s1[2]) == sort(s2[0], s2[2]) and sort(s1[1], s1[3]) == sort(s2[1], s2[3]).
Complexity Analysis
Time: O(1) (fixed length 4).
Space: O(1).
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public boolean canBeEqual(String s1, String s2) {
char a0 = s1.charAt(0), a2 = s1.charAt(2);
char b0 = s2.charAt(0), b2 = s2.charAt(2);
char a1 = s1.charAt(1), a3 = s1.charAt(3);
char b1 = s2.charAt(1), b3 = s2.charAt(3);
boolean evenEqual = (Math.min(a0, a2) == Math.min(b0, b2))
&& (Math.max(a0, a2) == Math.max(b0, b2));
boolean oddEqual = (Math.min(a1, a3) == Math.min(b1, b3))
&& (Math.max(a1, a3) == Math.max(b1, b3));
return evenEqual && oddEqual;
}
}func canBeEqual(s1 string, s2 string) bool {
a0, a2 := s1[0], s1[2]
b0, b2 := s2[0], s2[2]
a1, a3 := s1[1], s1[3]
b1, b3 := s2[1], s2[3]
evenEqual := minByte(a0, a2) == minByte(b0, b2) && maxByte(a0, a2) == maxByte(b0, b2)
oddEqual := minByte(a1, a3) == minByte(b1, b3) && maxByte(a1, a3) == maxByte(b1, b3)
return evenEqual && oddEqual
}
func minByte(a, b byte) byte {
if a < b {
return a
}
return b
}
func maxByte(a, b byte) byte {
if a > b {
return a
}
return b
}class Solution {
public:
bool canBeEqual(string s1, string s2) {
bool evenEqual = min(s1[0], s1[2]) == min(s2[0], s2[2])
&& max(s1[0], s1[2]) == max(s2[0], s2[2]);
bool oddEqual = min(s1[1], s1[3]) == min(s2[1], s2[3])
&& max(s1[1], s1[3]) == max(s2[1], s2[3]);
return evenEqual && oddEqual;
}
};class Solution:
def canBeEqual(self, s1: str, s2: str) -> bool:
even1 = tuple(sorted((s1[0], s1[2])))
even2 = tuple(sorted((s2[0], s2[2])))
odd1 = tuple(sorted((s1[1], s1[3])))
odd2 = tuple(sorted((s2[1], s2[3])))
return even1 == even2 and odd1 == odd2var canBeEqual = function(s1, s2) {
const min = (a, b) => (a < b ? a : b);
const max = (a, b) => (a > b ? a : b);
const evenEqual = min(s1[0], s1[2]) === min(s2[0], s2[2])
&& max(s1[0], s1[2]) === max(s2[0], s2[2]);
const oddEqual = min(s1[1], s1[3]) === min(s2[1], s2[3])
&& max(s1[1], s1[3]) === max(s2[1], s2[3]);
return evenEqual && oddEqual;
};中文
题目概述
给定长度为 4 的字符串 s1 和 s2,你可以反复执行两种交换:交换 s1[0] 与 s1[2],交换 s1[1] 与 s1[3]。判断 s1 是否能变成 s2。
核心思路
下标被分成两个互不干扰的组:偶数位 {0,2} 与奇数位 {1,3}。操作只能在组内交换,不能跨组移动字符。所以两组字符的“多重集合”必须分别相同。
最优算法
分别比较偶数位与奇数位的两字符排序结果是否一致即可。
sort(s1[0], s1[2]) == sort(s2[0], s2[2]) 且 sort(s1[1], s1[3]) == sort(s2[1], s2[3])。
复杂度分析
时间复杂度:O(1)(长度固定为 4)。
空间复杂度:O(1)。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public boolean canBeEqual(String s1, String s2) {
char a0 = s1.charAt(0), a2 = s1.charAt(2);
char b0 = s2.charAt(0), b2 = s2.charAt(2);
char a1 = s1.charAt(1), a3 = s1.charAt(3);
char b1 = s2.charAt(1), b3 = s2.charAt(3);
boolean evenEqual = (Math.min(a0, a2) == Math.min(b0, b2))
&& (Math.max(a0, a2) == Math.max(b0, b2));
boolean oddEqual = (Math.min(a1, a3) == Math.min(b1, b3))
&& (Math.max(a1, a3) == Math.max(b1, b3));
return evenEqual && oddEqual;
}
}func canBeEqual(s1 string, s2 string) bool {
a0, a2 := s1[0], s1[2]
b0, b2 := s2[0], s2[2]
a1, a3 := s1[1], s1[3]
b1, b3 := s2[1], s2[3]
evenEqual := minByte(a0, a2) == minByte(b0, b2) && maxByte(a0, a2) == maxByte(b0, b2)
oddEqual := minByte(a1, a3) == minByte(b1, b3) && maxByte(a1, a3) == maxByte(b1, b3)
return evenEqual && oddEqual
}
func minByte(a, b byte) byte {
if a < b {
return a
}
return b
}
func maxByte(a, b byte) byte {
if a > b {
return a
}
return b
}class Solution {
public:
bool canBeEqual(string s1, string s2) {
bool evenEqual = min(s1[0], s1[2]) == min(s2[0], s2[2])
&& max(s1[0], s1[2]) == max(s2[0], s2[2]);
bool oddEqual = min(s1[1], s1[3]) == min(s2[1], s2[3])
&& max(s1[1], s1[3]) == max(s2[1], s2[3]);
return evenEqual && oddEqual;
}
};class Solution:
def canBeEqual(self, s1: str, s2: str) -> bool:
even1 = tuple(sorted((s1[0], s1[2])))
even2 = tuple(sorted((s2[0], s2[2])))
odd1 = tuple(sorted((s1[1], s1[3])))
odd2 = tuple(sorted((s2[1], s2[3])))
return even1 == even2 and odd1 == odd2var canBeEqual = function(s1, s2) {
const min = (a, b) => (a < b ? a : b);
const max = (a, b) => (a > b ? a : b);
const evenEqual = min(s1[0], s1[2]) === min(s2[0], s2[2])
&& max(s1[0], s1[2]) === max(s2[0], s2[2]);
const oddEqual = min(s1[1], s1[3]) === min(s2[1], s2[3])
&& max(s1[1], s1[3]) === max(s2[1], s2[3]);
return evenEqual && oddEqual;
};
Comments