[복습] 알고리즘 기초 1/2 201-자료구조1(연습+참고)

Leejaegun·2025년 11월 11일

코딩테스트 시리즈

목록 보기
49/49

1. 단어뒤집기

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

s = input().rstrip()
stack = []
res = ""
inside_tag = False

for ch in s:
    if ch == "<":
        while stack:
            res += stack.pop()
        inside_tag = True
        res += ch
    elif ch == ">":
        inside_tag = False
        res += ch
    
    elif inside_tag:
        res += ch
    elif ch == " ":
        while stack:
            res += stack.pop()
        res += " "
    else:
        stack.append(ch)
        

while stack:
    res += stack.pop()

print(res)

🧩 단어 뒤집기 (BOJ 17413)에서 배운 점

1️⃣ inside_tag로 태그 내부/외부 구분

  • < → 태그 시작, > → 태그 끝.
  • inside_tag = True/False 로 현재 위치가 태그 안인지 밖인지를 추적.
  • 이 플래그 덕분에 “언제 스택에 쌓고(pop으로 뒤집을지)”를 결정할 수 있었다.
    → 태그 에서는 스택을 이용해 단어 뒤집기,
    → 태그 에서는 그대로 출력.

2️⃣ res(결과 문자열)를 따로 유지

  • 바로 print() 하지 않고,
    하나의 완성된 문자열로 쌓은 뒤 마지막에 출력.
  • 이유: 태그·단어·공백이 뒤섞여 있어서 즉시 출력하면 순서 관리가 어렵기 때문.
  • res는 최종 결과를 구성하는 완전한 문자열 버퍼 역할을 한다.

3️⃣ 공백 처리(" ") 시점 구분

  • 공백이 나오면 “단어가 끝났다”는 뜻이므로
    스택 안의 문자를 모두 pop() 하여 역순으로 res에 추가.
  • 그런 다음 공백도 그대로 붙인다.
    → 이로써 <tag> 밖 단어만 정확히 뒤집히고, 태그나 공백의 원형은 유지된다.

요약하자면 핵심은

문자 단위 순회 + 상태 전환(inside_tag) + 스택을 이용한 부분 뒤집기
였다.

2. 쇠막대기

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

import sys 
input = sys.stdin.readline
s = input().strip()
stack = []
count = 0

for i in range(len(s)):
    if s[i] == "(":
        stack.append("(")
    else:
        stack.pop()
        if s[i-1] == "(": #laser
            count += len(stack)
        else:
            count += 1

print(count)

배운점_ 코드는 간단해보이는데 솔직히 너무 어려웠다;; 거의 손도 못대서, 그냥 외워버림
(1) stack 을 사용하되 레이저를 사용

()(((()())(())()))(())

예시


전체 흐름 표

인덱스문자현재 스택 상태설명조각 수 변화누적 count
0((쇠막대기 시작0
1)레이저 (() 조합) → 자른 조각 없음+00
2((새 막대 시작0
3(( (새 막대 시작0
4(( ( (새 막대 시작0
5(( ( ( (새 막대 시작0
6)( ( (레이저! 스택길이=3 → +3조각+33
7(( ( ( (새 막대 시작3
8)( ( (레이저! 스택길이=3 → +3조각+36
9)( (쇠막대기 끝 → 마지막조각 +1+17
10(( ( (새 막대 시작7
11(( ( ( (새 막대 시작7
12)( ( (레이저! 스택길이=3 → +3조각+310
13)( (쇠막대기 끝 → 마지막조각 +1+111
14)(쇠막대기 끝 → 마지막조각 +1+112
15(( (새 막대 시작12
16)(레이저! 스택길이=1 → +1조각+113
17)쇠막대기 끝 → 마지막조각 +1+114
18((새 막대 시작14
19(( (새 막대 시작14
20)(레이저! 스택길이=1 → +1조각+115
21)쇠막대기 끝 → 마지막조각 +1+116
22⚠️ 마지막 큰 막대의 닫힘 시 조각 +1 (누락 보정)+117

핵심 해석

  • 6, 8, 12, 16, 20번째 문자들이 모두 레이저입니다.
    각각 그 시점의 스택(즉, 열린 쇠막대기) 개수만큼 자름.
  • 각 쇠막대기가 닫히는 )마지막 조각 1개를 더 만듦.
  • 총합은 17조각이 정확히 맞습니다.

요약 원리

  1. '(' → 스택에 push (새 막대 시작)

  2. ')'이 나오면:

    • 바로 앞이 '(' → 레이저 → stack.pop()count += len(stack)
    • 아니면 → 막대기 닫힘 → stack.pop(), count += 1
  3. 마지막까지 더한 총 count = 17

3. 후위표기식2

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

N = int(input())
expr = input().strip()
values = [int(input()) for _ in range(N)]
#print(values)
op = ["+","-","*","/"]
stack = []

for ch in expr:
    if ch.isalpha():
        stack.append(values[ord(ch) - ord("A")])
    else:
        a = stack.pop()
        b = stack.pop()
        if ch == "+":
            stack.append(b+a)
        elif ch == "-":
            stack.append(b-a)
        elif ch == "*":
            stack.append(b*a)
        else:
            stack.append(b/a)

for i in stack:
    print(f"{i:.2f}")

💡 배운 점 정리 (후위표기식2)

1️⃣ 변수 매핑 (values 리스트 + ord 사용)

  • 입력에서 받은 각 알파벳(A, B, C, …)을 숫자값으로 바꾸기 위해 values 리스트를 사용한다.
  • ord(ch) - ord('A')로 ‘A’를 0, ‘B’를 1처럼 인덱스로 변환하여 values에 접근하면
    A → values[0], B → values[1] 형태로 자연스럽게 매핑된다.

2️⃣ 스택 연산 순서 주의

  • 피연산자는 스택에 push, 연산자를 만나면 두 개를 pop한다.
    여기서 두 번째 pop된 값이 왼쪽 피연산자, 첫 번째 pop된 값이 오른쪽 피연산자다.

  • 따라서 항상

    a = stack.pop()
    b = stack.pop()

    로 두고, b - a, b / a 순으로 계산해야 한다.
    (연산자를 만난 뒤 pop하는 방식으로 쓰면 헷갈리고 코드 가독성이 떨어진다.)

3️⃣ 출력 형식 — 소수점 둘째자리

  • 최종 결과를 소수점 둘째 자리까지 출력해야 하므로

    print(f"{value:.2f}")

    형식을 사용한다.

  • 이 밖에도 알아두면 좋은 포맷팅:

    • f"{num:05d}" → 정수 앞에 0을 채워 5자리로 (00042)
    • f"{num:.3f}" → 소수점 아래 3자리까지 표시 (3.142)

즉, 핵심은
① 문자 인덱싱을 ord로 매핑,
② 스택의 연산 순서 유지,
③ 포맷팅으로 정확한 출력 형식 맞추기
이 세 가지다.

profile
Lee_AA

0개의 댓글