2026.08.08 의 코테 기록
오늘은 프로그래머스 Lv.1 문제를 여러 개 풀면서,
문제를 해결하는 과정에서 부족했던 Python 문법과 자료구조 개념을 정리했다.
1. 「서울에서 김서방 찾기」를 풀면서 index()를 배웠다
문제는 문자열 배열 seoul에서 "Kim"의 위치를 찾아 문자열로 반환하는 문제였다.
처음에는 enumerate()를 이용해서 직접 위치를 찾으려고 했다.
def solution(seoul):
for i, word in enumerate(seoul):
if word == "Kim":
return f"김서방은 {i}에 있다"
이 방법도 정답이지만, 문제에서 "Kim"이 반드시 한 번 존재한다고 했기 때문에 index()를 사용할 수 있었다.
index() 메서드를 알게되었다.
def solution(seoul):
index = seoul.index("Kim")
return f"김서방은 {index}에 있다"
index()
리스트에서 특정 값이 처음 등장하는 인덱스를 반환한다.
arr = ["Jane", "Kim", "Tom"]
arr.index("Kim")
# 1
이번 문제를 통해 문제를 직접 구현하기 전에 Python에 이미 존재하는 메서드를 활용할 수 있는지 확인해야 한다는 것을 배웠다.
2. 「최솟값 제거하기」를 풀면서 remove()와 pop()을 다시 확인했다
최솟값을 제거하는 문제를 풀면서 처음에는 다음과 같이 작성했다.
min_value = min(arr)
for i in arr:
if i == min_value:
arr.pop()
하지만 이 코드는 잘못된 방법이었다.
pop()은 기본적으로 마지막 원소를 제거하는 메서드이기 때문이다.
최솟값을 제거하려면 최솟값의 위치를 찾아야 한다.
min_value = min(arr)
arr.remove(min_value)
따라서 문제는 다음과 같이 간단하게 해결할 수 있다.
def solution(arr):
if len(arr) == 1:
return [-1]
arr.remove(min(arr))
return arr
remove()와 pop()의 차이
arr.remove(3)
→ 값이 3인 원소를 제거
arr.pop(2)
→ 인덱스 2의 원소를 제거
그리고
arr.pop()
→ 인덱스를 생략하면 마지막 원소를 제거
따라서 값을 기준으로 제거할 때는 remove(), 위치를 기준으로 제거할 때는 pop()을 사용한다.
3. count()가 무엇인지 확인했다
문제를 풀면서 count()가 단순히 "글자 수를 세는 함수"인지 궁금했는데,
정확히는 특정 값이 몇 번 등장하는지를 세는 메서드이다.
문자열에서 사용할 수 있다.
s = "banana"
s.count("a")
# 3
리스트에서도 사용할 수 있다.
arr = [1, 2, 1, 3, 1]
arr.count(1)
# 3
문자열의 경우 대소문자를 구분한다.
s = "pP"
s.count("p")
# 1
따라서 "p"와 "P"를 모두 세려면:
s = s.lower()
p_count = s.count("p")
y_count = s.count("y")
처럼 사용할 수 있다.
4. 2차원 배열 문제를 풀면서 완전탐색을 다시 공부했다
오늘 가장 어려웠던 문제 중 하나는 공원에 놓을 수 있는 가장 큰 돗자리를 찾는 문제였다.
park가 2차원 배열로 주어지고, "-1"이 연속으로 존재하는 정사각형 공간을 찾아야 했다.
처음에는 가로 방향으로 "-1"이 몇 개 연속되어 있는지 확인하려고 했다.
하지만 단순히 한 행에 "-1"이 많이 있다고 해서 정사각형을 만들 수 있는 것은 아니었다.
예를 들어:
-1 -1 -1
-1 -1 -1
-1 -1 -1
처럼 가로와 세로가 동시에 연속되어야 정사각형이 된다.
그래서 특정 위치를 정사각형의 시작점으로 잡고, 그 위치에서 정사각형 전체를 검사해야 한다.
기본적인 형태는:
for r in range(rows):
for c in range(cols):
...
이고, 특정 크기의 정사각형을 검사한다면:
for r in range(rows - size + 1):
for c in range(cols - size + 1):
for i in range(size):
for j in range(size):
if park[r+i][c+j] != "-1":
...
처럼 여러 겹의 반복문이 필요하다.
여기서 중요한 것은 반복문 자체를 외우는 것이 아니라:
r, c
→ 정사각형의 시작 위치
i, j
→ 시작 위치에서 정사각형 내부를 탐색
park[r+i][c+j]
→ 현재 검사하고 있는 칸
이라는 구조를 이해하는 것이다.
오늘 느낀 점
나는 2차원 배열 문제에서 두 개의 반복문을 이용해 행과 열을 탐색하는 것에는 익숙해지고 있지만, 특정 영역을 검사하기 위해 반복문이 추가되는 순간 많이 어려워진다는 것을 알게 됐다.
따라서 앞으로 2차원 배열 문제를 더 풀면서 반복문 구조 자체에 익숙해질 필요가 있다.
5. 이후 해시 문제로 넘어갔다
다음으로 프로그래머스의 「완주하지 못한 선수」 문제를 풀었다.
문제의 조건은 참가자 중 단 한 명만 완주하지 못했다는 것이다.
처음에는 다음과 같은 방법을 생각했다.
for person in completion:
participant.remove(person)
완주한 사람을 참가자 배열에서 하나씩 제거하면 마지막에 남는 사람이 완주하지 못한 선수이기 때문이다.
논리 자체는 이해할 수 있는 방법이었다.
하지만 이 문제는 해시 문제였고, 참가자가 최대 100,000명이기 때문에 dict를 이용하는 방법을 공부하게 되었다.
6. 해시를 공부했다
문제를 풀면서 Hash, Hash Map, hash(), dict가 각각 무엇인지 헷갈렸다.
정리하면:
Hash
데이터를 해시 함수를 이용하여 해시값으로 변환하는 개념이다.
Hash Function
입력 데이터를 해시값으로 변환하는 함수이다.
Python에서는:
hash("hello")
처럼 사용할 수 있다.
Hash Map
해시를 이용하여 Key-Value 형태로 데이터를 저장하는 자료구조이다.
Python의 dict가 대표적인 해시맵이다.
count = {
"mislav": 2,
"stanko": 1
}
따라서 코딩테스트에서 해시 문제라고 하면 Python에서는 우선 dict와 set을 떠올리는 것이 중요하다.
7. dict.get()을 배우면서 빈도수 세기를 이해했다
해시 문제를 풀면서 다음 코드를 보게 되었다.
count[x] = count.get(x, 0) + 1
처음에는 이 문법이 이해되지 않았다.
get()은 다음과 같이 동작한다.
dict.get(key, default)
즉,
count.get(x, 0)
은
x라는 Key가 있으면 그 값을 가져오고, 없으면 0을 가져온다.
는 의미다.
따라서:
count[x] = count.get(x, 0) + 1
은 결국
x가 지금까지 등장한 횟수를 가져온 다음 1을 더한다.
는 의미이다.
예를 들어:
participant = ["mislav", "stanko", "mislav", "ana"]
라면:
count = {}
for person in participant:
count[person] = count.get(person, 0) + 1
결과:
{
"mislav": 2,
"stanko": 1,
"ana": 1
}
이 된다.
8. 완주한 선수의 개수를 차감한다
완주자 배열을 이용해서 개수를 하나씩 감소시킨다.
for person in completion:
count[person] -= 1
예를 들어:
참가자
mislav → 2
stanko → 1
ana → 1
에서 완주자가:
stanko
ana
mislav
라면:
mislav → 1
stanko → 0
ana → 0
이 된다.
따라서 마지막에 값이 1 이상인 사람이 완주하지 못한 선수다.
전체 코드는:
def solution(participant, completion):
count = {}
for person in participant:
count[person] = count.get(person, 0) + 1
for person in completion:
count[person] -= 1
for person in count:
if count[person] > 0:
return person
9. 오늘 배운 것
오늘은 새로운 개념을 처음부터 공부하고 문제를 푼 것이 아니라, 문제를 풀면서 막힌 부분을 하나씩 찾아서 개념을 공부했다.
오늘의 흐름을 정리하면 다음과 같다.
프로그래머스 문제 풀이
↓
Python 메서드 사용법 부족
↓
count(), remove(), pop(), index() 정리
↓
2차원 배열 문제에서 반복문 구조가 어려움
↓
행/열 탐색과 특정 영역 탐색 이해
↓
해시 문제 풀이
↓
Hash / Hash Map / dict 개념 공부
↓
dict.get()을 이용한 빈도수 세기 이해
특히 오늘 가장 중요한 부분은 문제를 보고 어떤 자료구조나 알고리즘을 사용해야 하는지 바로 떠올리는 경험이 아직 부족하다는 것이다.
하지만 문제를 풀다가 막힌 부분을 개념으로 연결해서 공부하면 단순 암기보다 실제 문제에서 활용하는 방법을 익힐 수 있기 때문에, 앞으로도 이런 방식으로 문제를 풀어나가려고 한다.
'코테' 카테고리의 다른 글
| SWEA D1 풀이 후 배운 점 정리 Python3 (0) | 2026.08.04 |
|---|