알고리즘과 자료 구조 - 기초 - 이진탐색

인생노잼시기·2021년 6월 12일
0

Binary Search 이진 탐색
정렬된 상태에서 반으로 쪼개가며 찾는 요소가 있는지 탐색하는 방식

이진탐색트리에서 순환열거형 indirect가 유용하다고 하는데?

순환 열거형 indirect

열거형 항목의 연관값이 열거형 자신의 값이고자 할 때

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let final = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
func evaluate(_ expression: ArithmeticExpression) -> Int {
    switch expression {
    case .number(let value):
        return value
    case .addition(let left, let right):
        return evaluate(left) + evaluate(right)
    case .multiplication(let left, let right):
        return evaluate(left) * evaluate(right)
    }
}
let result: Int = evaluate(final)
print(result)   //18
let numbers = [11, 59, 3, 2, 53, 17, 31, 7, 19, 67, 47, 13, 37, 61, 29, 43, 5, 41, 23]
numbers.firstIndex(of: 43)  //O(n)

// 선형탐색은 시간복잡도가 O(n)이지만, 값이 없을 경우 탐색이 무의미해진다
func linearSearch<T: Equatable>(_ a: [T], _ key: T) -> Int? {
    for i in 0 ..< a.count {
        if a[i] == key {
            return i
        }
    }
    return nil
}
linearSearch(numbers, 43)

// 이진탐색의 선행조건은 정렬이 된 상태여야한다는 것이다
// 재귀적인 방식
func binarySearch<T: Comparable>(_ a: [T], key: T, range: Range<Int>) -> Int? {
    if range.lowerBound >= range.upperBound {
        return nil
    } else {
        let midIndex = range.lowerBound + (range.upperBound - range.lowerBound) / 2
        if a[midIndex] > key {
            return binarySearch(a, key: key, range: range.lowerBound ..< midIndex)
        } else if a[midIndex] < key {
            return binarySearch(a, key: key, range: midIndex+1 ..< range.upperBound)
        } else {
            return midIndex
        }
    }
}

let binaryNumbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67]
binarySearch(binaryNumbers, key: 43, range: 0 ..< numbers.count)    //13

//반복문 방식
func binarySearch<T: Comparable>(_ a: [T], _ key: T) -> Int? {
    var lowerBound = 0
    var upperBound = a.count
    while lowerBound < upperBound {
        let midIndex = lowerBound + (upperBound-lowerBound)/2
        if a[midIndex] == key {
            return midIndex
        } else if a[midIndex] < key {
            lowerBound = midIndex + 1
        } else {
            upperBound = midIndex
        }
    }
    return nil
}

binarySearch(binaryNumbers, 43) //13

반복문 방식이 간단해 보인다
자주 쓰이니 외워두면 좋다고 한다 😵‍💫


파라메트릭 서치

Parametric Search

: 원하는 조건을 만족하는 가장 알맞은 값을 찾는 문제
: 최적화 문제를 결정 문제로 바꾸어 해결하는 기법

최적화 문제: 최대한 높이거나 최대한 낮추거나
결정 문제: 예/아니오 로 답하는 문제

떡볶이 떡 만들기

떡의 최소 길이를 만족하는
떡 절단기의 최대길이 구하는 문제

떡의 최소 길이를 만족하는지의 여부를 예/아니오로 대답하면서
이진탐색을 해서 문제를 풀면 된다

https://velog.io/@msi753/이분탐색#1654

profile
인생노잼

0개의 댓글