Leetcode 2337. 移动片段获得字符串

目录

2337. 移动片段得到字符串 - 力扣(LeetCode)

解题思路

策略1:碰撞(互扰) --> 保持原状

策略2:两遍扫描


2337. 移动片段得到字符串 - 力扣(LeetCode)

解题思路

根据题目“L”只能向左移动,“R”只能向右移动。值得注意的是“L”和“R”为占位符,即不可互穿过。

基于此,如果我们提出非占位符“_”后,两个字符串序列应该一致。 所以,我们可以进行一次扫描。但是,"_"的位置对于我们的答案有所影响,所以我们不能真正的完全无视它。

策略1:碰撞(互扰) --> 保持原状

这里我们知道一个点。以示例1为例子,我们知道应该是“R”字符应该是按照顺序匹配的。但是,我们率先扫描到是左边的“R”。而在移动中间的字符时,我们“R”是收到影响的。但是我们使用一个策略就是假定“R”与“R”之间是可以互换的。那么我们先后匹配的问题就得以解决。

为了方便理解,我们举一个例子:

target = “__R_____R”

start = "R(1)R(2)_____"

为了方便说明,我们将start中的R做出标记以示区别。

步骤1:

start = “_R(2)R(1)____”

步骤2:

start = “__R(1)_____R(2)”

AC代码如下:

class Solution {
public:
    bool canChange(string start, string target) {
        int n = start.length();
        int i = 0, j = 0;
        while (i < n && j < n) {
            while (i < n && start[i] == '_') {
                i++;
            }
            while (j < n && target[j] == '_') {
                j++;
            }
            if (i < n && j < n) {
                if (start[i] != target[j]) {
                    return false;
                }
                char c = start[i];
                if ((c == 'L' && i < j) || (c == 'R' && i > j)) {
                    return false;
                }
                i++;
                j++;
            }
        }
        while (i < n) {
            if (start[i] != '_') {
                return false;
            }
            i++;
        }
        while (j < n) {
            if (target[j] != '_') {
                return false;
            }
            j++;
        }
        return true;
    }
};

 可以说因为采取策略1,所以我们只需要一次扫描即可。当然 “越位” 情况是显然错误的。

策略2:两遍扫描

关注到“L”的匹配优先匹配左边,“R”的匹配优先匹配右边。如果你没有想到策略1。那么就可以试试策略2:两遍扫描。

AC代码:

class Solution {
public:
    bool canChange(string start, string target) {
        int len = start.size();
        int i = 0, j = 0;
        //判断L的位序是否正确
        for (; i < len && j < len;i += 1, j += 1) {
            while (i < len && start[i] == '_') i += 1;
            while (j < len && target[j] == '_') j += 1;

            if (i == len && j < len || i < len && j == len) return false;
            if (i < len && j < len && start[i] != target[j]) return false;
            
            if (i < len && start[i] == 'R') continue;
            if (i < j) return false; 
        }
        while (i < len) {
            if (start[i] == 'L') return false;
            i += 1;
        }
        while (j < len) {
            if (target[j] == 'L') return false;
            j += 1;
        }

        //判断R的位序是否正确
        for (i = len - 1, j = len - 1; i >= 0 && j >= 0;i -= 1, j -= 1) {
            while (i >= 0 && start[i] == '_') i -= 1;
            while (j >= 0 && target[j] == '_') j -= 1;

            if (i >= 0 && j < 0 || i < 0 && j >= 0) return false;
            if (i >= 0 && j >= 0 && start[i] != target[j]) return false;
            
            if (i >= 0 && start[i] == 'L') continue;
            if (i > j) return false; 
        }
        while (i >= 0) {
            if (start[i] == 'R') return false;
            i -= 1;
        }
        while (j >= 0) {
            if (target[j] == 'R') return false;
            j -= 1;
        }

        return true;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值