데크나 힙처럼 다해주는건 아닌데 대충 도와준다!
이진탐색을 도와준다는게 어려워보이지만 그냥 정렬되어 있는 리스트에서 정렬을 흩트리지 않아도 되는 부분의 '인덱스'를 엄청 빠른 속도로 찾아주는 모듈이다.
.bisect(literable, value) : 이터러블한 객체, 찾는 값을 입력하면 그 값의 인덱스를 반환한다. 그 값의 인덱스가 없을때는 여기에 insert하면 정렬이 안깨질 것 같은 값을 오른쪽에다가 반환한다. 어쨌든 값 자체가 반환되는게 아니라는 것에 주의!
(bisect와 bisect_right는 같은 일을 한다.)
import bisect
result = []
scores = [33, 99, 77, 70, 89, 90, 100] # 애들이 받은 점수
grades = [60, 70, 80, 90] # 기준점수를 등급으로 바꿔주자
for score in scores:
pos = bisect.bisect(grades, score)
# 학생들의 점수를 grades = 기준에 넣는다고 가정했을때 어디 들어가면 될까
grade = 'FDCBA'[pos] # bisect는 인덱스만 리턴한다.
result.append(grade)
print(result)
['F', 'A', 'C', 'C', 'B', 'A', 'A']
.bisect_left(literable, value) : 이터러블한 객체, 찾는 값을 입력하면 얘는 왼쪽에서부터 세어서 그 값의 인덱스를 반환한다. 이상 초과 미만을 구현하기 좋다. 그 값의 인덱스가 없을때는 여기에 insert하면 정렬이 안깨질 것 같은 값을 인덱스의 왼쪽에 반환한다. 왼쪽 오른쪽으로 나뉘는 걸 제외하면 같은 기능이다.
bisect.insort(literable, value) : insert와 비슷한 역할, 정렬이 될 수 있는 위치를 자동으로 찾아서 들어간다!
insort_right도 있다!
>>> import bisect
>>> a = [60, 70, 80, 90]
>>> bisect.insort(a, 85)
>>> a
[60, 70, 80, 85, 90]
import bisect
def count_bi(nums, value):
ri = bisect(nums, value)
li = bisect_left(nums, value)
return ri - li
nums = [-1, -3, 5, 5, 4, 7, 1, 7, 2, 5, 6]
nums.sort() # 정렬은 필수
print(count_bi(nums, 5))
3
import bisect
def count_bi(nums, left_value, right_value):
ri = bisect(nums, right_value)
li = bisect_left(nums, left_value)
return ri - li
nums = [-1, -3, 5, 5, 4, 7, 1, 7, 2, 5, 6]
nums.sort() # 정렬은 필수
print(count_bi(nums, 5, 7)) # 5 ~ 7이 몇개나 있는지 구하기
6
bisect, bisect_left, insort 이거 세개만 알면 되고 추가로 효율성을 위해서 알면 좋은 거! 함수 안에 ,구분자로 들어가는 lo와 hi이다.
bisect.bisect_left(a, x, lo=0, hi=len(a)) # 리스트, 값, 왼쪽, 오른쪽
lo, hi는 left와 right를 의미한다.
if문 사용시 다음에 주의해야 한다고 써있는데
bisect_left()
a[mid] < target => lo = mid + 1
a[mid] >= target => hi = mid
bisect_right()
a[mid] <= target => lo = mid + 1
a[mid] > target => hi = mid
범위를 어느정도 알고 있을때 줄어드는 부분 이해하기!
bisect_left()는 중복이 있는 경우, hi를 줄여 최대한 왼쪽으로,
bisect_right()는 lo을 늘려 최대한 서치범위를 줄이면 좋다!