两种解法(35行/13行,复杂度都是O(n)):
python35行O(n):
- 统一向左和向右倒下
- 叠加两个数组判断最终状态
def build_seq(s, flag='R', stop='L', start=0, end=-1, step=1):
# flag 开始倒的标志
ts, beg_collapse = s.copy(), False
for i in range(start, end, step):
if beg_collapse:
if ts[i] == stop:
beg_collapse = False
else:
ts[i] = flag
elif ts[i] == flag:
beg_collapse = True
return ts
s = [i for i in input()] # for python 3
l2r = build_seq(s, 'R', 'L', 0, len(s), 1) # 先全部安排向右倒
r2l = build_seq(s, 'L', 'R', len(s)-1, -1, -1) # 再全部安排向左倒
res, i = [ord(i)-ord(j) for i, j in zip(l2r, r2l)], 0
while i < len(s):
cal = abs(res[i])
if cal == 0: # '.'-'.' or 'R'-'R' or 'L'-'L'
res[i] = l2r[i]
elif cal == 36: # abs('R'-'.')=36
res[i] = 'R'
elif cal == 30: # abs('L'-'.')=30
res[i] = 'L'
elif cal == 6: # abs('R'-'L')=6
start = i
while abs(res[i]) == 6:
i += 1
half = (i-start)//2
res[start+half] = '.' # 中间不倒
res[start: start+half] = ['R'] * half # 左边一半右倒
res[i-half: i] = ['L'] * half # 右边一半左倒
i -= 1
i += 1
print(''.join(res)) 更巧的解法是投影法:复杂度O(n)
- 依旧是双方向扫两次数组;
- 从左往右扫描时考虑向右倒下的方块的影子,每过一格影子长度减1,遇到'R'重置影长、遇到'L'清空影长、遇到'.'投影非负影长;同理,右往左扫描时考虑左倒方块的影子;
- 对两个方向的影子数组求差 —— 以下文代码为例,右倒数列减去左倒数列,则差大于0是'R',小于0为'L',等于0为'.'。
def func(s, length, flag='R', stop='L'):
shadow, ts = 0, [0] * length
for i in range(length):
shadow = 0 if s[i] == stop else (length if s[i] == flag else max(shadow-1, 0))
ts[i] = shadow
return ts
s = [i for i in raw_input()] # for python 2.7
l = len(s)
l2r, r2l = func(s, l, 'R', 'L'), func(s[::-1], l, 'L', 'R')[::-1]
for i in range(l):
cal = l2r[i] - r2l[i]
s[i] = '.' if cal == 0 else ('L' if cal < 0 else 'R')
print(''.join(s)) 
京公网安备 11010502036488号