LeetCode 838 Push Dominoes (二点法,模拟)

244 篇文章 0 订阅
37 篇文章 0 订阅

There are n dominoes in a line, and we place each domino vertically upright. In the beginning, we simultaneously push some of the dominoes either to the left or to the right.

After each second, each domino that is falling to the left pushes the adjacent domino on the left. Similarly, the dominoes falling to the right push their adjacent dominoes standing on the right.

When a vertical domino has dominoes falling on it from both sides, it stays still due to the balance of the forces.

For the purposes of this question, we will consider that a falling domino expends no additional force to a falling or already fallen domino.

You are given a string dominoes representing the initial state where:

  • dominoes[i] = 'L', if the ith domino has been pushed to the left,
  • dominoes[i] = 'R', if the ith domino has been pushed to the right, and
  • dominoes[i] = '.', if the ith domino has not been pushed.

Return a string representing the final state.

Example 1:

Input: dominoes = "RR.L"
Output: "RR.L"
Explanation: The first domino expends no additional force on the second domino.

Example 2:

Input: dominoes = ".L.R...LR..L.."
Output: "LL.RR.LLRRLL.."

Constraints:

  • n == dominoes.length
  • 1 <= n <= 105
  • dominoes[i] is either 'L''R', or '.'.

题目链接:https://leetcode.com/problems/push-dominoes/

题目大意:同时给一组多米诺骨牌若干个向左或向右的推力,两个相同方向的力不会叠加,相反方向的力遇到会抵消,求最终的牌面

题目分析:记录每个给推力的点会影响到的连续的左边或右边的骨牌数即可,详细见注释

19ms,时间击败84.12%

class Solution {
    class FallInfo {
        int pos, len, dir; // 0 -> left, 1 -> right
        FallInfo(int p, int l, int d) {
            this.pos = p;
            this.len = l;
            this.dir = d;
        }
    }
    public String pushDominoes(String dominoes) {
        char[] s = dominoes.toCharArray();
        int cur = 0, rpos = -1, lpos = -1, n = s.length, cnt = 0;
        FallInfo[] falls = new FallInfo[n];
        boolean[] vis = new boolean[n];
        while (cur < n) {
            if (s[cur] == 'L') {
                if (rpos == -1) {
                    // 第一个L且左边没有R
                    falls[cnt++] = new FallInfo(cur, cur, 0);
                } else if (rpos < cur) {
                    if (!vis[rpos]) {
                        // 当前的R只受到其右边第一个L的力的影响,最终会结果是一半R,一半L
                        vis[rpos] = true;
                        int len = (cur - rpos + 1) / 2 - 1;
                        falls[cnt++] = new FallInfo(rpos, len, 1);
                        falls[cnt++] = new FallInfo(cur, len, 0);
                    } else {
                        // 两个相邻的L之间都是L
                        falls[cnt++] = new FallInfo(cur, cur - lpos - 1, 0);
                    }
                }
                lpos = cur;
            } else if (s[cur] == 'R') {
                if (rpos > lpos) {
                    // 两个相邻的R之间都是R
                    falls[cnt++] = new FallInfo(rpos, cur - rpos, 1);
                }
                rpos = cur;
            }
            cur++;
        }
        if (rpos > lpos) {
            // 最后一个R且右边没有L
            falls[cnt++] = new FallInfo(rpos, n - rpos - 1, 1);
        }
        for (int i = 0; i < cnt; i++) {
            if (falls[i].dir == 0) {
                for (int j = falls[i].pos; j >= falls[i].pos - falls[i].len; j--) {
                    s[j] = 'L';
                }
            } else {
                for (int j = falls[i].pos; j <= falls[i].pos + falls[i].len; j++) {
                    s[j] = 'R';
                }
            }
        }
        return String.valueOf(s);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值