推多米诺

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"
说明:第一张多米诺骨牌没有给第二张施加额外的力。

解法:相邻标记

解题思路:

我们假设每一个’.‘都是被包在’L’,'R’之间,那么就有以下的情况:

  • 如果我们有 “A…B”,当 A = B,那么就变成 “AAAAAA”。
  • 如果我们有 “R…L”,那么结果会变成 “RRRLLL” 或者 “RRR.LLL” 如果点的个数是奇数。如果初始标记的坐标是 i 和 j,我们可以检查距离 k-i 和 j-k 来决定位置 k 的形态是 ‘L’,‘R’ 还是 ‘.’。
  • 如果我们有 “L…R”,就什么都不做,跳过。

代码如下:

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'; //左边界,主要是为了使第一个元素也能被'L','R'包起

        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) //遍历每一对'L','R'
        {
            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);
    }
}

解法来源

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值