leetcode-838:推多米诺

简介: leetcode-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.."

解题

方法一:BFS

参考链接

由于题目的意思,每1秒,就会有一个会倒,因此可以使用BFS,每一层时间相同,给下一个时刻,施加力,如果该时刻受力平衡(2个力)就忽略,受力不平衡(1个力)就继续传递。

class Solution {
public:
    string pushDominoes(string dominoes) {
        int n=dominoes.size();
        queue<int> q;
        vector<int> time(n,-1);//记录时间,未访问的为-1
        vector<string> force(n);//记录力,(每个点最多只会有2个力)
        for(int i=0;i<n;i++){
            if(dominoes[i]!='.'){
                q.push(i);
                time[i]=0;
                force[i].push_back(dominoes[i]);
            }
        }
        string res(n,'.');
        while(!q.empty()){
            int i=q.front();
            q.pop();
            if(force[i].size()==1){//只有 只到受一个力的 才会继续进行。 如果受到2个力,说明平衡,直接忽略
                char f=force[i][0];//当前的 力
                res[i]=f;
                int ni=f=='L'?i-1:i+1;//下一个索引 next index
                if(ni>=0&&ni<n){
                    if(time[ni]==-1){//如果下一个点未访问过
                        q.push(ni);
                        time[ni]=time[i]+1;
                        force[ni].push_back(f);
                    }
                    else if(time[ni]==time[i]+1){//如果下一个点访问过,且时间一致,说明受力平衡
                        force[ni].push_back(f);
                    }
                }
            }
        }
        return res;
    }
};

方法二:双指针(模拟)

1、LL之间的全L

2、RR之间的全R

3、LR不变

4、RL中间靠

5、最左边默认有个L,最右边默认有个R,这样方便处理

class Solution {
public:
    string pushDominoes(string dominoes) {
        dominoes='L'+dominoes+'R';
        string res;
        int l=0,r=1;//通过双指针,处理两指针中间的'.'
        while(r<dominoes.size()){
            while(r<dominoes.size()&&dominoes[r]=='.') r++;
            char leftChar=dominoes[l];
            char rightChar=dominoes[r];
            if(leftChar==rightChar){//情况1、2
                for(int i=l+1;i<r;i++){
                    res+=leftChar;
                }
            }
            else if(leftChar=='R'){//情况4:RL中间靠
                for(int i=0;i<(r-l-1)>>1;i++) res+='R';
                if(((r-l-1)&1)==1) res+='.';
                for(int i=0;i<(r-l-1)>>1;i++) res+='L';
            }
            else{//情况3:LR不变
                for(int i=l+1;i<r;i++) res+='.';
            }
            res+=rightChar;
            l=r;
            r++;
        }
        return res.substr(0,res.size()-1);
    }
};


相关文章
【 腾讯精选练习 50 题】14—合并两个有序数组【简单】
【 腾讯精选练习 50 题】14—合并两个有序数组【简单】
|
Java C++ Python
快讯:LeetCode中国正式上线《剑指Offer》题目,刷题真方便了!
近日,LeetCode中国[1]上线了一个全新的分类模块 LCOF “剑指 Offer[2]”。
4016 0
快讯:LeetCode中国正式上线《剑指Offer》题目,刷题真方便了!
|
3天前
每日一题!如约而至!(图片整理,寻找数组的中心下标)
每日一题!如约而至!(图片整理,寻找数组的中心下标)
16 0
|
6月前
|
算法 网络架构
代码随想录算法训练营第三十三天 | LeetCode 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果
代码随想录算法训练营第三十三天 | LeetCode 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果
33 0
|
9月前
当前年-往后推5年
当前年-往后推5年
25 0
|
12月前
|
算法 C++ Python
【每日算法Day 96】腾讯面试题:合并两个有序数组
【每日算法Day 96】腾讯面试题:合并两个有序数组
|
定位技术
leetcode每日一题:455. 分发饼干
leetcode每日一题:455. 分发饼干
|
消息中间件 存储 设计模式
我要实现一个推单功能了
以前都是作为消息接收方,接收消息。记得当时做支付的时候,接收第三方支付公司的各种消息,如支付成功、支付失败、退款成功、退款失败。