https://www.acmicpc.net/problem/5430
명령어 'R', 'D'로 조합된 함수와 정수 배열이 주어진다.
정수 배열에 대해 주어진 함수를 적용한 결과를 출력하는 문제이다.
함수의 길이와 배열의 길이가 모두 최대 100,000이므로 주어진 배열을 복사하는 등의 연산은 반드시 피해야 한다.
import sys
input = sys.stdin.readline
for _ in range(int(input())):
p = input().rstrip()
input() # n
nums = input().lstrip('[').rstrip(']\n').split(',')
if nums == ['']:
nums = []
start, end, step = 0, len(nums) - 1, 1
error = False
for op in p:
if op == 'R':
if step == 1:
start, end = end - len(nums), start - len(nums)
else:
start, end = end + len(nums), start + len(nums)
step = -step
else: # if op == 'D'
if step == 1 and start <= end:
start += 1
elif step == -1 and start >= end:
start -= 1
else:
error = True
break
if error:
print('error')
else:
print('[' + ','.join(nums[start:end + step:step]) + ']')
# 192ms
그래서 투 포인터를 활용한 방식에 접근해보았다.
아래 풀이2에서 살펴볼 코드에서 핵심적으로 사용되는 deque의 pop(), popleft() 역시 O(1)로 충분히 빠르긴 하지만 덧셈, 뺄셈으로 투 포인터를 움직이는 것이 더 빠를 수밖에 없다.
다만 투 포인터를 움직이는 과정에서 가독성은 조금 떨어지는 듯하다.
import sys
import collections
input = sys.stdin.readline
for _ in range(int(input())):
p = input().rstrip()
input() # n
nums = input().lstrip('[').rstrip(']\n').split(',')
if nums == ['']:
nums = []
nums = collections.deque(nums)
reverse = False # flag here.
error = False
for op in p:
if op == 'R':
reverse = not reverse
elif nums:
if reverse:
nums.pop()
else:
nums.popleft()
else:
error = True
break
if error:
print('error')
elif reverse:
print('[' + ','.join(reversed(nums)) + ']')
else:
print('[' + ','.join(nums) + ']')
# 268ms
deque를 활용한 다른 사람들의 풀이를 보고 짠 코드이다.
reverse라는 플래그 변수를 활용하는 방식으로, True이면 배열에 뒤에 있는 수를, False이면 앞에 있는 수를 pop한다.
이 방법 역시 배열을 매번 복사하지 않고 문제를 해결할 수 있다.
import sys
input = sys.stdin.readline
for _ in range(int(input())):
p = input().rstrip()
input() # n
nums = input().lstrip('[').rstrip(']\n').split(',')
if nums == ['']:
nums = []
start, end = 0, len(nums) - 1
reverse = False
error = False
for op in p:
if op == 'R':
reverse = not reverse
elif start <= end:
if reverse:
end -= 1
else:
start += 1
else:
error = True
break
if error:
print('error')
elif reverse:
print('[' + ','.join(reversed(nums[start:end + 1])) + ']')
else:
print('[' + ','.join(nums[start:end + 1]) + ']')
# 188ms
투 포인터와 플래그 변수 모두 활용한 풀이이다.
투 포인터만 활용한 풀이1에 비해 자잘한 연산들이 많이 줄어들었다.
무엇보다 풀이1보다 가독성이 훨씬 좋다고 생각한다.