Programming/Python

Python - bisect 예제

wave35 2025. 4. 23. 22:40

[ bisect 모듈 ]

bisect 모듈은 이진 탐색을 쉽게 쓸 수 있게 해주는 파이썬 표준 라이브러리

"정렬된 리스트"에 값을 효율적으로 삽입하거나 위치를 찾을 때 유용

 

 

[ 사용 함수 ]

함수 의미 반환값
bisect_left(a, x) 좌측 삽입 위치 탐색 x를 a에 넣을 때 왼쪽 인덱스
bisect_right(a, x) 우측 삽입 위치 탐색 x를 a에 넣을 때 오른쪽 인덱스
insort_left(a, x) bisect_left 위치에 삽입 리스트 a가 정렬된 상태 유지
insort_right(a, x) bisect_right 위치에 삽입 동일

 

 

[ 예제 ]

정렬 리스트에 중복을 허용하며 요소 삽입

import bisect

scores = [15, 22, 22, 30]
bisect.insort(scores, 22)      # insort == insort_right
print(scores)                  # [15, 22, 22, 22, 30]

 

리스트에 같은 값이 몇개 있는지 확인

a = [1, 2, 2, 2, 3, 4, 5]
lo = bisect.bisect_left(a, 2)   # 1
hi = bisect.bisect_right(a, 2)  # 4
count = hi - lo                 # 3

 

실시간 랭킹 유지

from bisect import insort_right

leaderboard = []          # (score, user) 튜플의 내림차순 리스트
def add_score(score, user):
    # 점수가 큰 순으로 정렬하기 위해 음수 key 사용, 튜플(-score, user)
    insort_right(leaderboard, (-score, user))

add_score(300, "Alice")
add_score(270, "Bob")
add_score(285, "Carol")

print(leaderboard[:3])    

>>> 출력
[(-300, 'Alice'), (-285, 'Carol'), (-270, 'Bob')]

 

 

[ 문제 ]

정수 배열 nums와 정수 n이 주어질 때, 증가 부분 수열(subsequence) 구하기

예제 1

nums = [2, 1, 5, 0, 4, 6]
n    = 3

가능한 증가 부분 수열 예: [2, 5, 6], [1, 4, 6], [0, 4, 6] 등이 있으므로
→ True

예제 2

nums = [5, 4, 3, 2, 1]
n    = 2

모든 값이 내림차순이므로 길이 2인 증가 부분 수열도 만들 수 없음
→ False

 

이 문제를 O(N log N) 시간에 해결하는 표준 기법(그리디+이진 탐색)을 구현한 예시

import bisect

def increasingSubsequence(nums, n):
    tail = []  # 각 길이별 수열의 최소 마지막 값 저장

    for num in nums:
        idx = bisect.bisect_left(tail, num)  # 현재 num이 들어갈 자리
        if idx == len(tail):
            tail.append(num)  # 새로운 길이의 수열이 생김
        else:
            tail[idx] = num  # 기존 길이 수열의 최소 마지막 값 갱신

        if len(tail) >= n:
            return True  # n중 수열 발견

    return False