题目来源:https://leetcode.cn/problems/swap-adjacent-in-lr-string/
大致题意:
给两个由 L、R、X 组成的字符串 start 和 end,其中字符串 start 中的 XL 可以被替换为 LX,RX 可以被替换为 XR。
求字符串 start 替换之后能否变成字符串 end
思路
已知第一个字符串中的 XL 可以被替换为 LX,RX 可以被替换为 XR
那么等价于在 L 左侧是 X 时,L 可以左移一位;R 右侧是 X 时,R 可以右移一位
那么什么情况下,L 需要左移呢?
举个例子,字符串 start 为 XXXLX,end 为 LXXXX,这时候就可以通过左移 start 中的 L 使 start 变为 end。而以下情况则不需要左移
- start 为 XLXXX,end 为 XXLXX。start 中的 L 在 end 左侧,而 L 只能左移,此时 start 无法变为 end
同理,当 start 中有 R 在 end 左侧时,可以通过右移 R 使位置相同,将 start 变为 end。但是start 中 R 在 end 右侧时则不可以
还有一种情况
- start 为 XRXLX,end 为 XLRXX。可以看到,在 R 右移时由于遇到右侧 的 L 会无法右移,L 左移时也会碰到 R 而无法左移,造成 start 无法变为 end
综合以上情况,可以使用双指针表示当前两个字符串的遍历位置,然后根据遍历位置的字符做如下判断。这里假设 idx1 表示 start 的遍历指针,idx2 表示 end 的遍历指针
- 若 idx1 和 idx2 对应字符有一个为 X,则对应的指针 +1
- 若 idx1 和 idx2 对应字符都不为 X。如果字符不相同,表示 L 遇到 R,或者 R 遇到 L,即 start 不能变为 end,直接返回 false;如果 idx1 对应字符为 L 且当前 idx1 指针在 idx2 左侧,或者 idx1 对应字符为 R 且当前 idx1 指针在 idx2 右侧,则为上述 start 不能变为 end 的条件,返回 false;否则,表示start 目前遍历的 L 和 R 移动后能与 end 对应位置一致,更新指针值
- 若 idx1 已经等于 start 长度,或者 idx2 已经等于 end 长度,则更新对方的指针值,并且判读对方字符是否为 X,若不为 X 表示两字符串含有的 L 或者 R 数量不同,返回 false
具体看代码:
class Solution {
public boolean canTransform(String start, String end) {
int n = start.length();
// 初始化指针值
int idx1 = 0;
int idx2 = 0;
// 当有一个指针未到对应字符串末尾时,遍历检查
while (idx1 < n || idx2 < n) {
// 若 start 已经遍历结束
if (idx1 == n) {
// 判断 end 是否有非 X 字符
if (end.charAt(idx2++) != 'X') {
return false;
}
continue;
}
// 若 end 已经遍历结束
if (idx2 == n) {
// 判断 start 是否有非 X 字符
if (start.charAt(idx1++) != 'X') {
return false;
}
continue;
}
// 若双指针对应字符都不为 X
if (start.charAt(idx1) != 'X' && end.charAt(idx2) != 'X') {
// 如果对应字符不相同,直接返回 false
if (start.charAt(idx1) != end.charAt(idx2)) {
return false;
}
// 判断是否有 start L 在 end L 左侧
// 或者 start R 在 end R 右侧的情况
if ((start.charAt(idx1) == 'L' && idx1 < idx2) || (start.charAt(idx1) == 'R' && idx1 > idx2)) {
return false;
}
// 更新指针
idx1++;
idx2++;
} else if (start.charAt(idx1) == 'X') { // 更新对应位置为 X 的指针值
idx1++;
} else {
idx2++;
}
}
return true;
}
}