838. 推多米诺 —— 2022.2.21

838. 推多米诺

题目

难度:中等
n 张多米诺骨牌排成一行,将每张多米诺骨牌垂直竖立。在开始时,同时把一些多米诺骨牌向左或向右推。

每过一秒,倒向左边的多米诺骨牌会推动其左侧相邻的多米诺骨牌。同样地,倒向右边的多米诺骨牌也会推动竖立在其右侧的相邻多米诺骨牌。

如果一张垂直竖立的多米诺骨牌的两侧同时有多米诺骨牌倒下时,由于受力平衡, 该骨牌仍然保持不变。

就这个问题而言,我们会认为一张正在倒下的多米诺骨牌不会对其它正在倒下或已经倒下的多米诺骨牌施加额外的力。

给你一个字符串 dominoes 表示这一行多米诺骨牌的初始状态,其中:
dominoes[i] = ‘L’,表示第 i 张多米诺骨牌被推向左侧,
dominoes[i] = ‘R’,表示第 i 张多米诺骨牌被推向右侧,
dominoes[i] = ‘.’,表示没有推动第 i 张多米诺骨牌。
返回表示最终状态的字符串。

示例 1:
输入:dominoes = “RR.L”
输出:“RR.L”
解释:第一张多米诺骨牌没有给第二张施加额外的力。

示例 2:
输入:dominoes = “.L.R…LR…L…”
输出:“LL.RR.LLRRLL…”

提示:
n == dominoes.length
1 <= n <= 105
dominoes[i] 为 ‘L’、‘R’ 或 ‘.’

详解

题目解析

简单来说就是给你一串的多米洛骨牌
然后在某一个时刻有一只无形的手会同时推动推动任意数量的骨牌
每个骨牌可以往左推也可以往右推
在骨牌被推动后它自然会往对应的方向倒,带动着旁边的骨牌一起倒

解题思路

1、如果当前为’L’ 或者 ‘R’ 时,最终状态一定不会改变;只有当前是 ‘.’ 最终状态才会受两边力的影响。
2、可以将连续的 ‘.’ 看成一个整体区间
如果当前为’.’,则加入区间,否则
分类讨论
(1)如果最左边受力为’L’ ,且最右边受力为 ‘L’,则这个区间全部变成 ‘L’
(2)如果最左边受力为’L’,且最右边受力为’R’,则这个区间不受影响
(3)如果最左边受力为’R’,且最右边受力为’R’,则这个区间全部变成’R’
(4)如果最左边受力为’R’,且最右边受力为’L’,则这个区间左边一半为’R’,右边一半为’L’,正中间那个不变
838. 推多米诺 —— 2022.2.21

代码

class Solution {
    /*
     * 1、如果当前为 'L' 或 'R' 时,最终的状态一定不会改变
     * 2、只有当前为 '.'时最终状态才受两边力的影响
     * 3、将连续的'.'看成一个整体区间
     *  (1)如果最左边受力为'L',最右边受力也为'L',则这个区间全部为'L'
     *  (2)如果最左边受力为'R',最右边受力也为'R',则这个区间全部为'R'
     *  (3)如果最左边受力为'R',最右边受力为为'L',则左边一半往右,右边一半往左,正中间那个不变
     */
    public String pushDominoes(String dominoes) {
        char[] chars = dominoes.toCharArray();
        int len = chars.length;
        for (int i = 0; i < len; i++) {
            // 只有当前为 '.' 最终状态才可能改变
            if (chars[i] == '.') {
                // 最左边
                int left = i;
                // 将连续的 '.' 看成一个整体
                while (i < len && chars[i] == '.') {
                    i++;
                }
                // 最右边
                int right = i;
                // 当前区间最左侧不会影响当前区间情况时
                if (left == 0 || chars[left - 1] == 'L') {
                    // 如果最右边是 'L'则全部为 'L' ('R'则这个区间不受影响)
                    if (right < len && chars[right] == 'L') {
                        for (int j = left; j < right; j++) {
                            chars[j] = 'L';
                        }
                    }
                } else if (right == len || chars[right] == 'R') { // 区间最右侧不会影响当前情况时
                    // 如果最左边是 'R'则全部为 'R'('L'则这个区间不受影响)
                    for (int j = left; j < right; j++) {
                        chars[j] = 'R';
                    }
                } else { // 最左侧为 'R' 并且 最右侧为 'L',向中间倒,只有最中间那个没有影响
                    while (left < right - 1) {
                        chars[left] = 'R';
                        chars[right - 1] = 'L';
                        left++;
                        right--;
                    }
                }
            }
        }
        return String.valueOf(chars);
    }
}

参考

https://leetcode-cn.com/problems/push-dominoes/solution/838-tui-duo-mi-nuo-cong-mei-you-bei-shi-0pek6/

上一篇:周赛D. Digging for Gold(扫描线)


下一篇:java 实现检测字符串是否只包含数字