[LeetCode] Push Dominoes 推多米诺骨牌
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.
Given a string "S" representing the initial state. S[i] = 'L', if the i-th domino has been pushed to the left; S[i] = 'R', if the i-th domino has been pushed to the right; S[i] = '.', if the i-th domino has not been pushed.
Return a string representing the final state.
Example 1:
Input: ".L.R...LR..L.."
Output: "LL.RR.LLRRLL.."
Example 2:
Input: "RR.L"
Output: "RR.L"
Explanation: The first domino expends no additional force on the second domino.
Note:
0 <= N <= 10^5- String
dominoescontains only'L','R'and'.'
这道题给我们摆好了一个多米诺骨牌阵列,但是与一般的玩法不同的是,这里没有从一头开始推,而是在很多不同的位置分别往两个方向推,结果是骨牌各自向不同的方向倒下了,而且有的骨牌由于左右两边受力均等,依然屹立不倒,这样的话骨牌就很难受了,能不能让哥安心的倒下去?!生而为骨牌,总是要倒下去啊,就像漫天飞舞的樱花,秒速五厘米的落下,回到最终归宿泥土里。喂,不要给骨牌强行加戏好么!~ 某个位置的骨牌会不会倒,并且朝哪个方向倒,是由左右两边受到的力的大小决定的,那么可以分为下列四种情况:
1)R....R -> RRRRRR
这是当两个向右推的操作连在一起时,那么中间的骨牌毫无悬念的都要向右边倒去。
2)L....L -> LLLLLL
同理,
当两个向左推的操作连在一起时,那么中间的骨牌毫无悬念的都要向左边倒去。
3)L....R -> L....R
当左边界的骨牌向左推,右边界的骨牌向右推,那么中间的骨牌不会收到力,所以依然保持坚挺。
4)R....L -> RRRLLL or R.....L -> RRR.LLL
当左边界的骨牌向右推,右边界的骨牌向左推时,就要看中间的骨牌个数了,若是偶数,那么对半分,若是奇数,那么最中间的骨牌保持站立,其余的对半分。
由于上述四种情况包含了所有的情况,所以我们的目标就是在字符串中找出中间是‘点’的小区间,为了便于我们一次遍历就处理完,我们在dominoes字符串左边加个L,右边加个R,这并不会影响骨牌倒下的情况。我们使用双指针来遍历,其中i初始化为0,j初始化为1,当j指向‘点’时,我们就跳过,目标是i指向小区间的左边界,j指向右边界,然后用 j-i-1 算出中间‘点’的个数,为0表示中间没有点。若此时 i>0,则将左边界加入结果res中。若左右边界相同,那么中间的点都填成左边界,这是上述的情况一和二;若左边界是L,右边界是R,则是上述的情况三,中间还是保持点不变;若左边界是R,右边界是L,则是情况四,那么先加 mid/2 个R,再加 mid%2 个点,最后加 mid/2 个L即可。然后i更新为j,继续循环即可,参见代码如下:
解法一:
class Solution {
public:
string pushDominoes(string dominoes) {
string res = "";
dominoes = "L" + dominoes + "R";
for (int i = , j = ; j < dominoes.size(); ++j) {
if (dominoes[j] == '.') continue;
int mid = j - i - ;
if (i > ) res += dominoes[i];
if (dominoes[i] == dominoes[j]) res += string(mid, dominoes[i]);
else if (dominoes[i] == 'L' && dominoes[j] == 'R') res += string(mid, '.');
else res += string(mid / , 'R') + string(mid % , '.') + string(mid / , 'L');
i = j;
}
return res;
}
};
下面这种解法遍历了两次字符串,第一次遍历是先把R后面的点全变成R,同时累加一个cnt数组,其中cnt[i]表示在dominoes数组中i位置时R连续出现的个数,那么拿题目中的例子1来说,第一次遍历之后,原dominoes数组,修改后的dominoes数组,以及cnt数组分别为:
.L.R...LR..L..
.L.RRRRLRRRL..
我们可以发现cnt数字记录的是R连续出现的个数,第一次遍历只模拟了所有往右推倒的情况,很明显不是最终答案,因为还需要往左推,那么就要把某些点变成L,已经把某些R变成点或者L,这时我们的cnt数组就非常重要,因为它相当于记录了往右推的force的大小。第二次遍历是从右往左,我们找所有L前面的位置,若其为点,则直接变为L。若其为R,那么也有可能变L,此时就要计算往左的force,通过 cnt[i+1] + 1 获得,然后跟往右的force比较,若此位置往右的force大,说明当前骨牌应该往左倒,更新此时cnt[i]为往左的force。若此时左右force相等了,说明当前骨牌不会向任意一遍倒,改为点即可,最终修改后的dominoes数组和cnt数组分别为:
LL.RR.LLRRLL..
解法二:
class Solution {
public:
string pushDominoes(string dominoes) {
int n = dominoes.size();
vector<int> cnt(n);
for (int i = ; i < n; ++i) {
if (dominoes[i - ] == 'R' && dominoes[i] == '.') {
dominoes[i] = 'R';
cnt[i] = cnt[i - ] + ;
}
}
for (int i = n - , cur = ; i >= ; --i) {
if (dominoes[i + ] != 'L') continue;
cur = cnt[i + ] + ;
if (dominoes[i] == '.' || cnt[i] > cur) {
dominoes[i] = 'L';
cnt[i] = cur;
} else if (dominoes[i] == 'R' && cnt[i] == cur) {
dominoes[i] = '.';
}
}
return dominoes;
}
};
类似题目:
Shortest Distance to a Character
参考资料:
https://leetcode.com/problems/push-dominoes/
https://leetcode.com/problems/push-dominoes/discuss/132332/C%2B%2BJavaPython-Two-Pointers
https://leetcode.com/problems/push-dominoes/discuss/132932/C%2B%2B-2-pass-scan-O(2N)-13ms
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Push Dominoes 推多米诺骨牌的更多相关文章
- [Swift]LeetCode838. 推多米诺 | Push Dominoes
There are N dominoes in a line, and we place each domino vertically upright. In the beginning, we si ...
- LeetCode.1128-等价多米诺骨牌对的数量(Number of Equivalent Domino Pairs)
这是小川的第394次更新,第428篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第259题(顺位题号是1128).给定多米诺骨牌列表,当且仅当(a == c且b == d ...
- Java实现 LeetCode 838 推多米诺(暴力模拟)
838. 推多米诺 一行中有 N 张多米诺骨牌,我们将每张多米诺骨牌垂直竖立. 在开始时,我们同时把一些多米诺骨牌向左或向右推. 每过一秒,倒向左边的多米诺骨牌会推动其左侧相邻的多米诺骨牌. 同样地, ...
- 【LeetCode】1128. Number of Equivalent Domino Pairs 等价多米诺骨牌对的数量(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典统计 代码 复杂度分析 日期 题目地址:http ...
- 省选训练赛第4场D题(多米诺骨牌)
题目来自FZU2163 多米诺骨牌 Time Limit: 1000 mSec Memory Limit : 32768 KB Problem Description Vasya很喜欢排多米诺 ...
- poj 1717==洛谷P1282 多米诺骨牌
Dominoes Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6571 Accepted: 2178 Descript ...
- 用1 x 2的多米诺骨牌填满M x N矩形的方案数(完美覆盖)
题意 用 $1 \times 2$ 的多米诺骨牌填满 $M \times N$ 的矩形有多少种方案,$M \leq 5,N < 2^{31}$,输出答案模 $p$. 分析 当 $M=3$时,假设 ...
- 【Tsinghua OJ】多米诺骨牌(domino)问题
(domino.c/cpp)[问题描述] 小牛牛对多米诺骨牌有很大兴趣,然而她的骨牌比较特别,只有黑色和白色的两种.她觉 得如果存在连续三个骨牌是同一种颜色,那么这个骨牌排列便是不美观的.现在她有n个 ...
- 【01背包】洛谷P1282多米诺骨牌
题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点.现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|.例如在图8-1中,S1=6+1+1+1=9, ...
随机推荐
- spring boot集成netty-服务端和客户端demo
项目源码:https://github.com/zhzhair/spring-boot-netty.git 项目启动说明:服务端--spring-boot-netty-server,客户端--spri ...
- Numerical Analysis
PART1 <求解方程> 1,二分法 def bisect(f,a,b,TOL=0.000004): u_a = a u_b = b while(u_b-u_a)/2.0 > TO ...
- Grunt 实战
专题截图:(注:这个截图没啥意义) 项目截图: 目录讲解: app/ //开发目录; c/ //开发编译完成css文件夹; i/ //开发img文件夹; j/ / ...
- Linux库多重依赖
源文件: //world.cpp #include <stdio.h> void world(void) { printf("world.\n"); } //hello ...
- Idea中一些常用设置
idea展开和折叠方法的快捷键 Ctrl+”+/-”,当前方法展开.折叠Ctrl+Shift+”+/-”,全部展开.折叠 idea中也有自定代码块的功能 //region 描述.....业务代码//e ...
- 项目debug启动不起来解决办法
debug起服务,读取文件可能会出错,eclipse自动加断点,这时候就卡住了,这时候eclipse——window——show view breakpoints-——remove all,重新启动t ...
- MathType7.X链接:https://pan.baidu.com/s/1rQ5Cwk5_CC9UgvgaYPVCCg 提取码:6ojq 复制这段内容后打开百度网盘手机App,操作更方便哦完美解压,无限使用
最近在写论文的过程中使用到了MathType,但是由于MathType30天使用已经过期,有些特殊符号用不了,于是开始找各种破解版.好吧,花了整整两个小时才算搞定,真是一部血泪史,现在把安装破解教程贴 ...
- HihoCoder - 1038 01背包 动态规划
#1038 : 01背包 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 且说上一周的故事里,小Hi和小Ho费劲心思终于拿到了茫茫多的奖券!而现在,终于到了小Ho领取奖励 ...
- golang slice 经典例题
arr := [...],,,,,,,,} s1 :=arr[:] s2 :=arr[:] s1=? //2,3,4,5 s2=? // 5,6 package main import " ...
- Angular 项目列表页
$ ng g m project 功能:项目列表显示,增加,修改,删除项目.邀请其它人员加入项目. 单一性原则:希望搭建多个组件,每个组件负责自己的功能. 一.project相关组件 $ ng g c ...