[BOJ] 5430 - AC

엄혜영·2024년 4월 22일
1
post-thumbnail

요즘 푸는 문제는 죄다 어찌저찌 출력은 잘 나오는데

막상 제출하면 틀렸거나 시간 초과다.

내 코드가 똥인걸 우째... 분석이나 잘 해보자.


문제의 코드

from collections import deque
import sys

testcase = int(input())

for i in range(testcase):
    order = sys.stdin.readline().strip('\n')
    listlength = int(sys.stdin.readline())
    acstr = sys.stdin.readline().strip('[]\n')
    error = False
    if len(acstr)==0:
        print('error')
        continue
    aclist = deque(map(int, acstr.split(',')))

    orderlist = list(order)
    for ord in orderlist:
        if ord=='R':
            aclist = list(aclist)
            aclist = aclist[::-1]
            aclist = deque(aclist)
        else:
            if len(aclist)==0:
                error = True
                break
            aclist.popleft()
    if error:
        print('error')
    else:
        aclist = list(aclist)
        print(aclist)

맨 첫 줄에 테스트 케이스의 개수를 입력받고

테스트 케이스 만큼 반복하며 출력을 해야하는 문제이다.

내가 짠 코드는 이중 for 문을 통해 문제를 해결하고 있다.

해당 문제를 풀기 위해서는 이것 이상으로 반복문을 줄일수는 없을 것이다.

그래서 결과로 시간초과가 나왔을 때 당황스러웠다.

아니... 더 이상 줄일게 없는데..?

내가 알던 네가 아냐

눈알 빠져라 코드를 보던 중 눈에 띈 슬라이싱

위의 코드에서는 R(뒤집기)를 하기 위해서 슬라이싱으로 리스트를 뒤집어주고 있다.

지금까지 아무 생각 없이 써도 아무 문제도 발생하지 않아서 몰랐는데,

슬라이싱이 생각보다 많은 시간을 잡아먹는다고 한다.

아니 나는 그냥 너가 빠른 애인줄 알았지....

Q. string slicing이 시간소요가 큰가요?
A. python 의 슬라이싱은 매번 새로운 객체를 만들어내는 O(n) 연산입니다.
블로그를 더 찾아보니 정확히는 O(b-a)의 시간 복잡도를 가진다고 한다.


그래서 문제가 되는 슬라이싱 관련 코드를 제거하고

뒤집기를 해야 하는지 판별하는 isR를 이용해

'R' 명령이 들어오면 ~isR을 해주었다.

'D' 명령이 들어오면 isR의 상태에 따라 pop()/popleft()를 한다.

+) 항상 디테일에 주의하자

위의 수정으로 시간 초과 문제를 벗어났는데 바로 함정에 빠졌다.

어려운 문제인가 했는데.........

리스트를 그냥 바로 출력했을 때 공백이 있던게 문제였던 것 같다.

ㅎㅎ...



해결 완료!

from collections import deque
import sys

testcase = int(input())

for i in range(testcase):
    order = list(sys.stdin.readline().strip('\n'))
    listlength = int(sys.stdin.readline())
    acstr = sys.stdin.readline().strip('[]\n')
    error = False
    isR = False
    if len(acstr)==0:
        aclist = deque()
    else:
        aclist = deque(map(int, acstr.split(',')))

    for ord in order:
        if ord=='R':
            isR = ~isR
        else:
            if len(aclist)==0:
                error = True
                break
            if ~isR:
                aclist.popleft()
            else:
                aclist.pop()
    if error:
        print('error')
        continue

    aclist = list(aclist)
    if isR:
        aclist = aclist[::-1]
    print('[', end='')
    for i in range(len(aclist)):
        if i==len(aclist)-1:
            print('{}'.format(aclist[i]), end='')
            break
        print('{},'.format(aclist[i]), end='')
    print(']')

+) 헷갈리기 쉬운 부분 정리

조건식에서 부정을 표현하기 위해 ! 연산자를 사용한다.

위의 코드에서는 문자열을 뒤접어야 할지 여부를 isR 변수로 알 수 있다.

만약, isR의 True 값을 False로 바꾸기 위해서 !isR로 써도 될까?

답은 아니오다.

위에 작성된 코드를 보면 알 수 있듯이 boolean 타입의 변수 값을 반전시키기 위해서 ~isR을 해주었다.

또는 not isR를 해주어도 된다.


참고 자료

string slicing이 시간소요가 큰가요?
★☆★☆★ [필독] AC FAQ ★☆★☆★
[Python] 파이썬 자료형 및 연산자의 시간 복잡도(Big-O) 총 정리

profile
누워있는게 좋은 완벽주의자

0개의 댓글

관련 채용 정보