LeetCode刷题笔记 838. 推多米诺

题目描述

一行中有 N 张多米诺骨牌,我们将每张多米诺骨牌垂直竖立。

在开始时,我们同时把一些多米诺骨牌向左或向右推。

在这里插入图片描述
每过一秒,倒向左边的多米诺骨牌会推动其左侧相邻的多米诺骨牌。

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

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

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

给定表示初始状态的字符串 “S” 。如果第 i 张多米诺骨牌被推向左边,则 S[i] = ‘L’;如果第 i 张多米诺骨牌被推向右边,则 S[i] = ‘R’;如果第 i 张多米诺骨牌没有被推动,则 S[i] = ‘.’。

返回表示最终状态的字符串。

示例 1:
输入:".L.R…LR…L…"
输出:“LL.RR.LLRRLL…”
示例 2:
输入:“RR.L”
输出:“RR.L”
说明:第一张多米诺骨牌没有给第二张施加额外的力。

Sample Code 1

class Solution {
    public String pushDominoes(String dominoes) {
        int N = dominoes.length();
        int[] indexes = new int[N+2];
        char[] symbols = new char[N+2];
        int len = 1;
        indexes[0] = -1;
        symbols[0] = 'L';

        for (int i = 0; i < N; ++i)
            if (dominoes.charAt(i) != '.') {
                indexes[len] = i;
                symbols[len++] = dominoes.charAt(i);
            }

        indexes[len] = N;
        symbols[len++] = 'R';

        char[] ans = dominoes.toCharArray();
        for (int index = 0; index < len - 1; ++index) {
            int i = indexes[index], j = indexes[index+1];
            char x = symbols[index], y = symbols[index+1];
            char write;
            if (x == y) {
                for (int k = i+1; k < j; ++k)
                    ans[k] = x;
            } else if (x > y) { // RL
                for (int k = i+1; k < j; ++k)
                    ans[k] = k-i == j-k ? '.' : k-i < j-k ? 'R' : 'L';
            }
        }

        return String.valueOf(ans);
    }
}

Sample Code 2

对字符串 S = ‘R.R…L’ 的模拟:我们从左向右暴力得到的结果为 [7, 6, 7, 6, 5, 4, 0],从右向左扫描的结果为 [0, 0, 0, -4, -5, -6, -7]。合并之后,合力为 [7, 6, 7, 2, 0, -2, -7] 所以最近结果为 RRRR.LL。

class Solution {
    public String pushDominoes(String S) {
        char[] A = S.toCharArray();
        int N = A.length;
        int[] forces = new int[N];

        // Populate forces going from left to right
        int force = 0;
        for (int i = 0; i < N; ++i) {
            if (A[i] == 'R') force = N;
            else if (A[i] == 'L') force = 0;
            else force = Math.max(force - 1, 0);
            forces[i] += force;
        }

        // Populate forces going from right to left
        force = 0;
        for (int i = N-1; i >= 0; --i) {
            if (A[i] == 'L') force = N;
            else if (A[i] == 'R') force = 0;
            else force = Math.max(force - 1, 0);
            forces[i] -= force;
        }

        StringBuilder ans = new StringBuilder();
        for (int f: forces)
            ans.append(f > 0 ? 'R' : f < 0 ? 'L' : '.');
        return ans.toString();
    }
}

Sample Code 3 (Fastest)

class Solution {
    public String pushDominoes(String dominoes) {
        char[] c = dominoes.toCharArray();
        int start = 0;

        for (int i = 0; i < c.length; i++) {
            if (c[i] == 'R') {
                for (int j = i + 1; j < c.length; j++) {
                    if (c[j] == '.') {
                        c[j] = 'R';
                    }else if(c[j] == 'R') {
                        i=j-1;
                        break;
                    }else if (c[j] == 'L') {
                        if ((i + j) % 2 == 0) {
                            c[(i + j) / 2] = '.';
                        }
                        for (int k = (j + i) / 2 + 1; k < j; k++) {
                            c[k] = 'L';
                        }
                        i = j;
                        break;
                    }
                }
            } else if (c[i] == 'L') {
                for (int k = i-1; k >= 0 ; k--) {
                    if (c[k] == '.') {
                        c[k] = 'L';
                    }else{
                        break;
                    }
                }
            }
        }
        return String.valueOf(c);
    }
}

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/push-dominoes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值