两种解法(35行/13行,复杂度都是O(n)):
python
35行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))