일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 파이썬 정렬
- DP
- 파이썬 자료형
- data type
- 데이터 통신과 컴퓨터 네트워크
- 리스트
- 노마드코더
- 데이터통신
- 라우팅
- 자료형
- RARP
- 북클럽
- 파이썬 연산자
- 이코테
- 노개북
- 시스템 소프트웨어
- OSI7계층모델
- CS
- 쉽게 배우는 데이터 통신과 컴퓨터 네트워크
- 기억장치
- 이것이 취업을 위한 코딩테스트다
- icmp
- 컴퓨터 동작방식
- 쿠키
- 컴퓨터네트워크
- GIT
- ARP
- IT5분잡학사전
- sort()
- 이것이 취업을 위한 코딩 테스트다
- Today
- Total
뚝딱햄 탈출기
[Python][백준 BOJ ] 10815. 숫자 카드 : 시간 초과 해결, 딕셔너리 vs 리스트, 이분 탐색 본문
[Python][백준 BOJ ] 10815. 숫자 카드 : 시간 초과 해결, 딕셔너리 vs 리스트, 이분 탐색
hyrmzz1 2024. 1. 8. 16:24접근 방식
입력으로 주어진 M개의 수와 상근이가 가지고 있는 숫자 카드 중 일치하는 값이 있는지 순차적으로 확인한다.
❌ Solution 1 - 시간 초과
import sys
n = int(sys.stdin.readline())
cards = list(map(int, sys.stdin.readline().split()))
m = int(sys.stdin.readline())
num = list(map(int, sys.stdin.readline().split()))
for i in num:
if i in cards:
print(1, end=" ")
else:
print(0, end=" ")
이 코드 내에서 시간이 오래 걸릴만한 부분은 if i in cards
라고 생각했다.
찾아보니 리스트는 요소 하나하나를 조회할 때 최악의 경우 O(n)의 시간 복잡도를 가진다하여 더 빠른 자료형을 사용해야겠다고 생각했다.
✅ Solution 2 - dictionary, set 이용
딕셔너리와 세트는 검색, 삽입 및 삭제 작업에 대해 O(1)의 시간 복잡도를 갖는다. (조회, 삽입, 삭제에 대해 내부적으로 동일한 해싱 메커니즘 사용)
리스트는 배열로 구현되며 목록 내에서 검색하면 목록의 각 요소를 반복하여 일치하는 항목을 찾기 때문에 최악의 경우 시간 복잡도는 O(n)이다.
따라서 검색 문제를 해결할 때, (특히 요소 수가 많고 조회 효율성이 중요한 경우) 딕셔너리와 세트를 사용하면 리스트보다 더 빠르게 해결할 수 있다.
딕셔너리는 키-값 쌍을 저장하는 반면, 세트은 고유한 요소를 저장한다.
따라서 키-값 쌍이 있는 경우 딕셔너리를 선택하고, 고유한 요소만 저장하고 값을 연결할 필요가 없는 경우에는 집합을 사용하자.
딕셔너리는 키-값 쌍을 저장하므로 집합에 비해 메모리 오버헤드가 약간 더 높을 수 있어 키-값 쌍이 필요하지 않다면 세트를 사용하는 것이 적절하다.
세트
import sys
n = int(sys.stdin.readline())
cards = set(map(int, sys.stdin.readline().split()))
m = int(sys.stdin.readline())
num = list(map(int, sys.stdin.readline().split()))
for i in num:
if i in cards:
print(1, end=" ")
else:
print(0, end=" ")
변수 cards는 상근이가 가진 카드에 적힌 숫자(중복 X)만을 저장하므로 set형을 이용하였다.
딕셔너리
import sys
n = int(sys.stdin.readline())
cards = list(map(int, sys.stdin.readline().split()))
m = int(sys.stdin.readline())
num = list(map(int, sys.stdin.readline().split()))
card_dict = {i: 0 for i in cards} # 딕셔너리 컴프리헨션
for i in num:
if i in card_dict:
print(1, end=" ")
else:
print(0, end=" ")
cards를 딕셔너리형으로 이용하려면 카드에 적힌 숫자를 키로 두고, 값은 필요 없으니 아무 숫자로 세팅해준다. (코드 내에선 0으로 세팅)
✅ Solution 3 - 이분 탐색
import sys
n = int(sys.stdin.readline())
cards = list(map(int, sys.stdin.readline().split()))
m = int(sys.stdin.readline())
num = list(map(int, sys.stdin.readline().split()))
def binary_search(arr, target):
start = 0
end = len(arr) - 1
while(start <= end):
mid = (start + end) // 2
if arr[mid] == target:
return True
elif arr[mid] > target:
end = mid - 1
else:
start = mid + 1
cards.sort()
for i in num:
if binary_search(cards, i): # True
print(1, end = " ")
else:
print(0, end = " ")
사실 이 문제는 이분 탐색을 연습하려고 푼 문제였다.
다만 cards
와 num
중 어느 것을 binary_search()
의 arr
로 설정해야할지 헷갈려서 처음 풀이에서 이분 탐색을 사용하지 않았다.
num이 cards 내에 있는지 확인해야 하니 binary_search()
의 arr
에는 cards
가 들어가면 된다.
이분 탐색을 이용하면 num과 같은 값이 cards에 있는지 확인할 때 모든 요소를 순차적으로 탐색하지 않아도 된다.
cards의 중간값(mid)부터 num과 비교해 num > mid
라면 범위를 절반으로 줄여 mid의 오른쪽에서만 num을 탐색할 수 있기 때문이다.
💭What I Learned
- 존재 여부를 탐색할 때 리스트(O(n))보다 딕셔너리(O(1))가 더 빠르다.
- 이분 탐색을 할 때 무엇을 탐색 대상으로 할 지 잘 생각해보자.
- 이 문제에서는 사용하지 않았지만 bisect()를 사용해 이분 탐색을 할 수도 있다.
https://www.acmicpc.net/problem/10815
10815번: 숫자 카드
첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,
www.acmicpc.net
'Algorithm & Data structure > 알고리즘 문제 풀이' 카테고리의 다른 글
[JS][TIL] reduce()를 사용해보자 : 프로그래머스 베스트앨범 (0) | 2024.04.03 |
---|---|
[Python][백준 BOJ Silver I] 1932. 정수 삼각형 : DP (0) | 2024.02.28 |
[Python][BOJ 백준][Silver II] 1406. 에디터, [Gold IV] 9935. 문자열 폭발 : 스택 아이디어 떠올리기 (0) | 2024.01.03 |
[Python][백준 BOJ Silver IV] 1269. 대칭 차집합 : set 자료형을 이용한 교집합/합집합/차집합 구하기 (1) | 2024.01.02 |
[Python][백준 BOJ Silver V] 2628. 종이 자르기 : 정렬, 리스트 컴프리헨션을 활용한 출력 (0) | 2023.12.16 |