4分钟
LeetCode算法手记:777.在LR字符串中交换相邻字符
在一个由 ‘L’ , ‘R’ 和 ‘X’ 三个字符组成的字符串(例如"RXXLRXRXL")中进行移动操作。
一次移动操作指用一个 “LX” 替换一个 “XL”,或者用一个 “XR” 替换一个 “RX”。
现给定起始字符串 start 和结束字符串 end,请编写代码,当且仅当存在一系列移动操作使得 start 可以转换成 end 时, 返回 True。
输入:start = "RXXLRXRXL", end = "XRLXXRRLX"
输出:True
解释:
我们可以通过以下几步将 start 转换成 end:
RXXLRXRXL ->
XRXLRXRXL ->
XRLXRXRXL ->
XRLXXRRXL ->
XRLXXRRLX
提示:
1 <= len(start) = len(end) <= 10000。
start 和 end 中的字符串仅限于’L’, ‘R’和’X’。
思路
如果一个start可以完成到end的转换,那么,两个字符串中L和R的相对位置一定会保持一致。
可以在start和end上分别各自定义指针i和j,跳过X直到第一个L或者R出现,此时判断s[i]和s[j]是否相等,如果不相等则不满足相对顺序,无法完成转换。
XL被LX替换,RX被XR替换,则意味着:
- 如果能完成转换,最终end中第N个L的下标,只能小于或等于start中第N个L的下标,即L只允许左移或原地停留。
- 如果能完成转换,最终end中第M个R的下标,只能大于或等于start中第M个R的下标,即R只允许右移或原地停留。
思路递推
以题目中的start = “RXXLRXRXL”, end = “XRLXXRRLX"为例:
- 找到第一个不为X的下标,此时i=0,j=1。
- 判断s[i] == s[j],此时结果为true。
- 判断i和j的顺序,由于两字符均为R,R只允许右移或原地停留,即j >= i,所以s[i]可以被转换至s[j],即XR替换RX。
- 找到第二个不为X的下标,此时i=3,j=2。
- 判断s[i] == s[j],此时结果为true。
- 判断i和j的顺序,由于两字符均为L,L只允许左移或原地停留,即j <= i,所以s[i]可以被转换至s[j],即LX替换XL。
- 找到第三个不为X的下标,此时i=4,j=5。
- 判断s[i] == s[j],此时结果为true。
- 判断i和j的顺序,由于两字符均为R,R只允许右移或原地停留,即j >= i,所以s[i]可以被转换至s[j],即XR替换RX。
- 找到第四个不为X的下标,此时i=6,j=6。
- 判断s[i] == s[j],此时结果为true。
- 判断i和j的顺序,由于两字符均为R,R只允许右移或原地停留,即j >= i,所以s[i]可以被转换至s[j],即原地停留。
- 找到第五个不为X的下标,此时i=8,j=7。
- 判断s[i] == s[j],此时结果为true。
- 判断i和j的顺序,由于两字符均为L,L只允许左移或原地停留,即j <= i,所以s[i]可以被转换至s[j],即LX替换XL。
- 此时i到达末尾,完成搜索,判断i是否和j相等,只有两个指针到达同样的位置,才能完成转换。
代码实现:
public static boolean canTransform(String start, String end) {
int length = start.length();
//定义双指针i和j,分别指向start和end
//1.分别找到start和end中第一个不为X的字符s[i]和s[j]
//2.判断s[i]是否和s[j]相等,若不相等,则不满足相对顺序,无法完成转换
//3.判断s[j]的顺序:L字符只允许向左转换,R字符只允许向右转换
//同时需要注意:start和end全由X组成的情况
int i = 0,j = 0;
while (i < length || j < length){
while (i < length && start.charAt(i) == 'X')
//找到start中第一个不为X的字符位置
i++;
while (j < length && end.charAt(j) == 'X')
//找到end中第一个不为X的字符位置
j++;
if (i == length || j == length)
//任意一边指针到头,说明当前字符串全由X组成,则另一个字符串也应该全由X组成才能完成转换
return i == j;
if (start.charAt(i) != end.charAt(j))
//判断s[i]是否和s[j]相等,若不相等,则不满足相对顺序,无法完成转换
return false;
if (start.charAt(i) == 'L' && i < j)
//L字符只允许向左转换,即转换后的下标j不应该大于i
return false;
if (start.charAt(i) == 'R' && i > j)
//R字符只允许向左转换,即转换后的下标j不应该小于i
return false;
i++;
j++;
}
return i == j;
}
public static void test(){
System.out.println(canTransform("RXXLRXRXL","XRLXXRRLX"));
System.out.println(canTransform("RXXLRXRXL","XRXLXRLLX"));
}