BOJ 5430번: AC [Python]

hysong·2022년 7월 4일
0

PS

목록 보기
11/15

📌 Problem.

https://www.acmicpc.net/problem/5430

명령어 'R', 'D'로 조합된 함수와 정수 배열이 주어진다.
정수 배열에 대해 주어진 함수를 적용한 결과를 출력하는 문제이다.

📌 Solution.

함수의 길이와 배열의 길이가 모두 최대 100,000이므로 주어진 배열을 복사하는 등의 연산은 반드시 피해야 한다.

1. 투 포인터

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)로 충분히 빠르긴 하지만 덧셈, 뺄셈으로 투 포인터를 움직이는 것이 더 빠를 수밖에 없다.
다만 투 포인터를 움직이는 과정에서 가독성은 조금 떨어지는 듯하다.

2. 플래그(Flag)

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한다.
이 방법 역시 배열을 매번 복사하지 않고 문제를 해결할 수 있다.

3. 투 포인터 & 플래그

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보다 가독성이 훨씬 좋다고 생각한다.

0개의 댓글