Medium
题目描述
在一个由 ‘L’、‘R’ 和 ‘X’ 字符组成的字符串中,如 “RXXLRXRXL”,一次移动包括用 “LX” 替换一个 “XL”,或者用 “XR” 替换一个 “RX”。给定起始字符串 start 和结束字符串 result,当且仅当存在一系列移动可以将 start 转换为 result 时,返回 True。
示例 1:
输入:start = "RXXLRXRXL", result = "XRLXXRRLX"
输出:true
解释:我们可以通过以下步骤将 start 转换为 result:
RXXLRXRXL ->
XRXLRXRXL ->
XRLXRXRXL ->
XRLXXRRXL ->
XRLXXRRLX
示例 2:
输入:start = "X", result = "L"
输出:false
约束条件:
- 1 <= start.length <= 10^4
- start.length == result.length
- start 和 result 只包含字符 ‘L’、‘R’ 和 ‘X’
提示: 可以将 L 和 R 视为水平线上的人,X 是空间。人不能相互穿越,也不能从 XRX 变为 RXX。
解题思路
解题思路
这道题的核心在于理解移动规则:
- “XL” → “LX”:L 可以向左移动穿过 X
- “RX” → “XR”:R 可以向右移动穿过 X
关键观察:
- 相对顺序不变:去除所有 X 后,L 和 R 的相对顺序必须保持不变
- 移动方向限制:L 只能向左移动,R 只能向右移动
- 位置约束:在 start 中的每个 L 在 result 中的位置不能更右,每个 R 在 result 中的位置不能更左
解法分析: 使用双指针分别遍历 start 和 result,跳过 X 字符,只比较 L 和 R:
- 首先检查去除 X 后的字符序列是否相同
- 然后检查每个字符的位置是否满足移动约束
算法步骤:
- 使用两个指针 i 和 j 分别指向 start 和 result
- 跳过 X 字符,找到下一个 L 或 R
- 比较字符是否相同,如果不同则返回 false
- 检查位置约束:L 在 result 中不能比在 start 中更右,R 在 result 中不能比在 start 中更左
- 继续处理直到遍历完成
代码实现
class Solution {
public:
bool canTransform(string start, string result) {
int n = start.length();
int i = 0, j = 0;
while (i < n || j < n) {
// 跳过start中的X
while (i < n && start[i] == 'X') i++;
// 跳过result中的X
while (j < n && result[j] == 'X') j++;
// 如果一个到达末尾,另一个也必须到达末尾
if (i == n && j == n) return true;
if (i == n || j == n) return false;
// 字符必须相同
if (start[i] != result[j]) return false;
// 检查位置约束
if (start[i] == 'L' && i < j) return false; // L不能向右移动
if (start[i] == 'R' && i > j) return false; // R不能向左移动
i++;
j++;
}
return true;
}
};
class Solution:
def canTransform(self, start: str, result: str) -> bool:
n = len(start)
i = j = 0
while i < n or j < n:
# 跳过start中的X
while i < n and start[i] == 'X':
i += 1
# 跳过result中的X
while j < n and result[j] == 'X':
j += 1
# 如果一个到达末尾,另一个也必须到达末尾
if i == n and j == n:
return True
if i == n or j == n:
return False
# 字符必须相同
if start[i] != result[j]:
return False
# 检查位置约束
if start[i] == 'L' and i < j:
return False # L不能向右移动
if start[i] == 'R' and i > j:
return False # R不能向左移动
i += 1
j += 1
return True
public class Solution {
public bool CanTransform(string start, string result) {
int n = start.Length;
int i = 0, j = 0;
while (i < n || j < n) {
// 跳过start中的X
while (i < n && start[i] == 'X') i++;
// 跳过result中的X
while (j < n && result[j] == 'X') j++;
// 如果一个到达末尾,另一个也必须到达末尾
if (i == n && j == n) return true;
if (i == n || j == n) return false;
// 字符必须相同
if (start[i] != result[j]) return false;
// 检查位置约束
if (start[i] == 'L' && i < j) return false; // L不能向右移动
if (start[i] == 'R' && i > j) return false; // R不能向左移动
i++;
j++;
}
return true;
}
}
var canTransform = function(start, result) {
const n = start.length;
let i = 0, j = 0;
while (i < n || j < n) {
// 跳过start中的X
while (i < n && start[i]
复杂度分析
| 复杂度类型 | 值 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(1) |
说明:
- 时间复杂度:O(n),其中 n 是字符串长度,每个字符最多被访问一次
- 空间复杂度:O(1),只使用了常数额外空间
相关题目
- . Move Pieces to Obtain a String (Medium)