图解LeetCode——777. 在LR字符串中交换相邻字符(难度:中等)

 一、题目

在一个由 'L' , 'R' 和 'X' 三个字符组成的字符串(例如"RXXLRXRXL")中进行移动操作。一次移动操作指用一个"LX"替换一个"XL",或者用一个"XR"替换一个"RX"。现给定起始字符串start和结束字符串end,请编写代码,当且仅当存在一系列移动操作使得start可以转换成end时, 返回True

二、示例

2.1> 示例 :

【输入】 start = "RXXLRXRXL", end = "XRLXXRRLX"
【输出】 True
【解释】我们可以通过以下几步将start转换成end: RXXLRXRXL -> XRXLRXRXL -> XRLXRXRXL -> XRLXXRRXL -> XRLXXRRLX

提示:

  • 1 <= len(start) = len(end) <= 10000
  • start和end中的字符串仅限于'L', 'R'和'X'。

三、解题思路

根据题意,我们可以知道“LX”可以替换为“XL”,“XR”可以替换为“RX”,所以,我们可以将其看成是X位置不变(即:以X为“轴”),去移动字符'L'或者'R'。那么根据题目描述的变化规则,'L'是只能向右侧移动,即:“LX”——>“XL”;'R'是只能向左侧移动,即:“XR”——>“RX”;

那么我们发现这种规律之后,我们就可以只关注字符'R'和'L'了。判断规律如下所示:

条件一:start中每位字符'L'的index,都要 大于等于 end中每位字符'L'的index。
条件二:start中每位字符'R'的index,都要 小于等于 end中每位字符'R'的index。

只有同时满足了上述两个条件,才可以确定start中的字符'R'和字符'L'是可以移动成为end中的字符'R'和字符'L'。而且,题目中的提示部分,已经告诉我们start和len的长度相同,并且start和end中的字符串仅限于'L', 'R'和'X',那么我们只需要再确定start与end中的字符'R'与字符'L'是一一对应的即可(即:个数都是相同的,可以一一对应上)。具体逻辑,请看下图所示:

四、代码实现

4.1> 实现1

class Solution {
    public boolean canTransform(String start, String end) {
        char[] startArray = start.toCharArray(), endArray = end.toCharArray();
        int j = 0, length = start.length();
        for (int i = 0; i < length; i++) {
            if (startArray[i] == 'X') continue;
            for (; j < length; j++) {
                 if (endArray[j] != 'X') break;               
            }
            if (j == length || startArray[i] != endArray[j]) return false;
            if (startArray[i] == 'L' && i < j) return false;// 'L'只能往左走
            if (startArray[i] == 'R' && i > j) return false;// 'R'只能往右走
            j++;
        }
        for (;j < length; j++)
            if (endArray[j] != 'X') return false;
        return true;
    }
}

4.2> 实现2

class Solution {
    public boolean canTransform(String start, String end) {
        char[] startArray = start.toCharArray(), endArray = end.toCharArray();
        int sIndex = 0, eIndex = 0, length = start.length();
        while (sIndex < length || eIndex < length) {
            Character sChar = null, eChar = null;
            for (int i = sIndex; i < length; i++) {
                if (startArray[i] != 'X') {
                    sIndex = i;
                    sChar = startArray[i];
                    break;
                }
            }
            for (int j = eIndex; j < length; j++) {
                if (endArray[j] != 'X') {
                    eIndex = j;
                    eChar = endArray[j];
                    break;
                }
            }
            if (sChar == null && eChar == null) return true;
            if ((sChar == null && eChar != null) || (sChar != null && eChar == null)) return false;
            if (!sChar.equals(eChar)) return false;
            if (sChar == 'L' && sIndex < eIndex) return false;// 'L'只能往左走
            if (sChar == 'R' && sIndex > eIndex) return false;// 'R'只能往右走
            sIndex++; eIndex++;
        }
        
        return true;
    }
}

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享 。

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值