====== algorithm.py ====== ===== binary_search ===== 이 함수는 deprecated 되었습니다. [[:ps:이진 검색#bisect_모듈을_이용한_파라메트릭_서치_구현]]을 참고해서 구현하세요 ==== 코드 ==== # N binary_search # I {"version": "1.0", "typing": ["Callable"]} def binary_search(beg: int, end: int, predicate: Callable[[int], bool]) -> int: """Returns the minimum int X in [beg, end) where predicate(X) is true.""" if not predicate(end - 1): raise ValueError while beg < end: mid = (beg + end) // 2 if predicate(mid): end = mid else: beg = mid + 1 return beg ==== 설명 ==== * 최소값, 즉 predicate(x)가 x=t에서 True일때, t를 리턴해주는 함수이다. * 만약 반대로 최대값, 즉 predicate(x)가 x<=t에서 True 이고 x>t에서 False일 때, t를 구해야 한다면, predicate를 negate시키고, 찾아진 값에서 1을 빼줌으로써 구할 수 있다. * x = binary_search(beg, end, lambda(x): not predicate(x)) - 1 ==== 이 코드를 사용하는 문제 ==== ---- struct table ---- schema: ps cols: site, prob_id, %title%, prob_level filter: teflib ~ *[binary_search]* csv: 0 ---- ===== nth_element ===== ==== 코드 ==== T = TypeVar('T') # N nth_element # I {"version": "1.0", "typing": ["Sequence, TypeVar"], "const": ["T"]} def nth_element(arr: Sequence[T], n: int, threshold: int = 500_000) -> T: """Returns n-th smallest element from given sequence.""" def nth_element_rec(arr, n): if len(arr) <= threshold: return sorted(arr)[n - 1] pivot = sorted([arr[0], arr[-1], arr[len(arr) // 2]])[1] sub = [el for el in arr if el < pivot] if n <= len(sub): return nth_element_rec(sub, n) sub = [el for el in arr if el > pivot] if (l := n - (len(arr) - len(sub))) > 0: return nth_element_rec(sub, l) return pivot if not 1 <= n <= len(arr): raise ValueError(f'n({n}) must be in [1, {len(arr)}]') return nth_element_rec(arr, n) ==== 설명 ==== * QuickSelect 알고리즘. 피벗은 median of 3로 구한다 * [[ps:선택 알고리즘]] 참고 * 시퀀스의 길이가 아주 클때에만 (적어도 500,000 이상) 사용할 가치가 있고, 그렇지 않으면 그냥 전체를 sorting해서 구하는 것이 더 효율적이다. ==== 이 코드를 사용하는 문제 ==== {{topic>ps:teflib:nth_element&nouser&nodate}}