题目:
In a string composed of 'L'
, 'R'
, and 'X'
characters, like "RXXLRXRXL"
, a move consists of either replacing one occurrence of "XL"
with "LX"
, or replacing one occurrence of "RX"
with "XR"
. Given the starting string start
and the ending string end
, return True
if and only if there exists a sequence of moves to transform one string to the other.
Example:
Input: start = "RXXLRXRXL", end = "XRLXXRRLX" Output: True Explanation: We can transform start to end following these steps: RXXLRXRXL -> XRXLRXRXL -> XRLXRXRXL -> XRLXXRRXL -> XRLXXRRLX
Note:
1 <= len(start) = len(end) <= 10000
.- Both start and end will only consist of characters in
{'L', 'R', 'X'}
.
思路:
我原来想到的方法是BFS或者DFS,逐个探索看看从start是否可以达到end,但是看到题目分类之后,觉得肯定会LTE,所以就没试(后来看到讨论里面果然不能用BFS和DFS)。
通过观察可以看到,在start中,L只能不断地往左移动,R只能不断地往右移动。那么给定start和end之后,我们只检查其中仅仅含有L和R的子串:如果发现在start中某个R出现在了end中对应的R之后,那么就返回false,因为该R无法再被往左移动到end的对应位置了;如果发现某个R出现在了end中对应的L之前,那么也返回false,因为该L无法再被往右移动到end中的对应位置了。
这种算法的时间复杂度为O(n),空间复杂度为O(1),可谓是最优算法了。
代码:
class Solution {
public:
bool canTransform(string start, string end) {
int i = 0, j = 0, n = start.length();
while (i < n && j < n) {
while (j < n && end[j] == 'X') {
++j;
}
while (i < n && start[i] == 'X') {
++i;
}
if (i == n && j == n) {
return true;
}
if (i == n || j == n || start[i] != end[j]) {
return false;
}
if (start[i] == 'R' && i > j) {
// R can only move right, but here R in start is after the corresponding R in end
return false;
}
else if (start[i] == 'L' && i < j) {
// L can only move left, but here L in start is before the corresponding L in end
return false;
}
++i, ++j;
}
return true;
}
};