题目链接
https://leetcode.cn/problems/swap-adjacent-in-lr-string/
题目来源于:第70场周赛 Q3 rating: 1938
类似题目:https://leetcode.cn/problems/move-pieces-to-obtain-a-string/
思路
题意的浅层描述是:start串的XL能被替换为LX,RX能被替换为XR。
对于start串的替换操作,稍加扩展可以得到:
- L能够越过左边的若干个X,但是不能越过L或R。
- R能够越过右边的若干个X,但是不能越过L或R。
例如 start=RXXLRXRXL -> RLXXXXRRL。
代码一
开两个vector来存两个子串中L、R的位置和字符,便于进行比较。
struct node{
int pos; // 在字符串中的位置
char val; // 字符
};
class Solution {
vector<node> start_LR;
vector<node> end_LR;
public:
bool canTransform(string start, string end) {
int n=start.size();
int m=end.size();
if (n!=m) {
return 0;
}
if(n==1){
// 特判
return start==end;
}
for(int i=0;i<n;i++){
if(start[i]!='X'){
start_LR.push_back({i,start[i]});
}
if(end[i]!='X'){
end_LR.push_back({i,end[i]});
}
}
// 首先,start串和end串中的L,R字符总数必须相同
if(start_LR.size()!=end_LR.size()){
return 0;
}
for(int i=0;i<start_LR.size();i++){
node st=start_LR[i];
node ed=end_LR[i];
if(st.val!=ed.val){
return 0;
}
if((st.val=='L'&&st.pos<ed.pos) || (st.val=='R'&&st.pos>ed.pos)){
// 当start串的L在end串的对应L的左边时,可以移动到end串的L位置;
// 当start串的R在end串的对应L的右边时,可以移动到end串的R位置;
return 0;
}
}
return 1;
} // end function
}; // end class
/*
"XRRXRX"
"RXLRRX"
ans: false
"XXXXXLXXXX"
"LXXXXXXXXX"
ans: true
"RXXLRXRXL"
"XRLXXRRLX"
ans: true
"X"
"L"
ans: true
"RXX"
"RXL"
ans: false
"XXXL"
"LXXR"
ans: false
"RXXLRXRXL"
"XRLXXRRLX"
ans: true
*/
代码二
与代码一相比,这个省一点时间和空间,但是细节比较麻烦。
class Solution {
public:
bool canTransform(string start, string end) {
int n = start.size();
int m = end.size();
if (n != m) {
return 0;
}
if(n == 1){
// 特判
return start==end;
}
int num1=0,num2=0,num3=0,num4=0;
for(int i=0;i<n;i++){
if(start[i]=='L'){
num1++;
}
if(start[i]=='R'){
num2++;
}
if(end[i]=='L'){
num3++;
}
if(end[i]=='R'){
num4++;
}
}
// 首先,start串和end串中的L,R字符总数必须相同
if(!(num1==num3&&num2==num4)){
return 0;
}
int i = 0, j = 0;
while (i < n) {
// printf("i=%d j=%d\n",i,j);
// 从i位置开始,找到start串为L或R的字符
while (start[i] == 'X') {
i++;
}
if(i==n){
break;
}
// 根据start[i]找end中下一个和start[i]相同的
while (j < m && end[j] != start[i]) { // 例如start[i]=R end[j]=X或L
// R和L不能互相越过对方
if ((start[i] == 'L' && end[j] == 'R') || (start[i] == 'R' && end[j] == 'L')) {
return 0;
}
// 越过X
j++;
}
if (j == m) { // 没找到相同的(比如全是X)
return 0;
}
assert(start[i] == end[j]);
if ( (start[i] == 'L' && j > i) || (start[i] == 'R' && i > j) ) {
return 0;
}
i++;
j++;
} // end while(i<n)
return 1;
} // end function
}; // end class