作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
关键词:力扣,LeetCode, Python, C++, Java, 838,多米诺
题目地址:https://leetcode.com/problems/push-dominoes/description/
题目描述
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 dominoes contains only ‘L’, ‘R’ and ‘.’
大家好,我是 @负雪明烛。👈👈 点击关注,优质题解不间断。
题目大意
推多米诺骨牌。
在起始的时候,都是站着的,然后同时像某些方向推,L
代表向左边推,R
代表向右边推,.
代表不推。
如果左右撞在一起,那么就受力平衡所以仍然站着。
另外,很重要的一点,如果一个牌倒在了另外一个已经倒了的牌上,不会给它施加任何力。换句话说,一个推倒了的牌("L"
或"R"
)只能对另一个站着的牌("."
)起作用。
解题方法
如果理解了「一个推倒了的牌只能对另一个站着的牌起作用」这句话那么基本上就能做出来这个题了,否则是做不出来的。
含义是:
- 两个相邻的被推倒的牌互不影响。
- 一张站立的牌(
"."
)的最终状态与离其两侧最近的"L"
或"R"
有关。
所以我们应该找出每个("."
)左右两边最近的两个被推倒了的牌,然后判断这两个牌是什么样子的即可,不用考虑这个区间以外的牌。因为这两张牌被推倒了,而这个区间外的其他牌不会对推倒了的牌起作用。
双指针
可以使用「双指针」的方式寻找 "."
左右两边距离最近的被推倒的牌。
在这两个被推倒了牌形成的区间里:
'R......R' => 'RRRRRRRR'
'R......L' => 'RRRRLLLL' or 'RRRR.LLLL'
'L......R' => 'L......R'
'L......L' => 'LLLLLLLL'
使用双指针算法:
l
指向区间的开始(指向"L"
或者"R"
);r
跳过所有的"."
,指向区间的结束(也指向"L"
或者"R"
)。- 此时区间的形状为
"X....Y"
,判断这个区间左右端点的"X"
、"Y"
是什么,确定中间的"."
的状态。
由于可能存在输入的dominoes
的最左边和最右边都有 "."
,那么形成不了"X....Y"
这样的区间。所以,下面的代码中,给dominoes
最左边添加了一个 "L"
,最右边添加了一个 "R"
,添加的这两个虚拟的牌不会影响dominoes
内部所有的牌的倒向,但是有助于我们形成区间,而且这两个添加的牌,也不会放到最终结果里。
代码如下:
class Solution(object):
def pushDominoes(self, d):
"""
:type dominoes: str
:rtype: str
"""
d = "L" + d + "R"
res = []
l = 0
for r in range(1, len(d)):
if d[r] == '.':
continue
mid = r - l - 1
if l: # 虚拟的牌不放入结果
res.append(d[l])
if d[l] == d[r]:
res.append(d[l] * mid)
elif d[l] == 'L' and d[r] == 'R':
res.append('.' * mid)
else:
res.append('R' * (mid // 2) + '.' * (mid % 2) + 'L' * (mid // 2))
l = r
return "".join(res)
参考资料:
https://leetcode.com/problems/push-dominoes/discuss/132332/C++JavaPython-Two-Pointers
时间复杂度
- 时间复杂度: O ( N ) O(N) O(N),其中 N N N 是数组长度;
- 空间复杂度:结果不算的话,是 O ( 1 ) O(1) O(1)。
总结
- 重要的永远是题意!理解题意,成功大半!
- 不妨向我一样画个图,能清晰很多!
日期
2018 年 9 月 15 日 ———— 天气转冷,小心着凉