기준(pivot)을 설정하고,
그 기준보다 큰지 작은지 판별하여 위치를 바꾸는 분할 정복 알고리즘이다.
분할 방법이 여러가지 존재하기 때문에 반드시 먼저 명시해야한다.
이번엔 첫번째 데이터를 기준으로 정하는 호어 분할(Hoare Partition)로 설정하여 진행해보자.
var data = [7, 5, 9, 0, 3, 1, 6, 2, 4, 8]
1. 탐색할 범위를 설정한다.
2. 피봇을 설정한다.
	data[1] 부터 탐색 -> data[2] = 9
3. 값을 비교하여 피봇 보다 큰지 작은지 여부를 판단한다.
	data[9] 부터 탐색 -> data[8] = 4
4. 피봇보다 큰 데이터와 작은 데이터의 위치를 Swap한다.
	data[2] = 4, data[8] = 9
5. 위의 과정을 재귀로 반복하여 pivot의 왼쪽과 오른쪽을 분할하여 계속 정렬해나간다.
var array = [5, 7, 9, 0, 3, 1, 6, 2, 4, 8]
func quickSort(_ array: inout [Int], start: Int, end: Int) {
    print("<< quickSort() 실행 >> ")
    print("0. start: \(start), end: \(end)")
    print("실행 전 : \(array)")
    print()
    if start >= end { return }          // -  원소가 1개인 경우 종료
    
    let pivot = start                   // 0. 기준  : 첫 번째 원소
    var left = start + 1                // 1. 왼쪽  : 시작위치 + 1
    var right = end                     // 2. 오른쪽 : 맨 끝
    print(">> pivot : \(pivot)")
    print(">> left : \(left)")
    print(">> right : \(right)")
    print()
    
    while left <= right {               // 3. 왼쪽 인덱스가 오른쪽 인덱스와 작거나 같다면 반복
        print(">> array[left] : \(array[left])")
        print(">> array[right] : \(array[right])")
        print()
        while (left <= end) && (array[left] <= array[pivot]) {
            left += 1                   // 4. 왼쪽부터 기준보다 큰 원소 찾기
            print("4. left += 1 >> \(left)")
        }
        while (right > start) && (array[right] >= array[pivot]) {
            right -= 1                  // 5. 오른쪽부터 기준보다 작은 원소 찾기
            print("5. right -= 1 >> \(right)")
        }
        if left > right {
            array.swapAt(right, pivot)  // 6. 엇갈렸다면 작은 데이터와 pivot 교체
            print("6. left가 right보다 커서 right, pivot 스왑 = \(pivot 기준 왼쪽은 작고, 오른쪽은 크도록 정렬 완료)")
        } else {
            array.swapAt(left, right)   // 7. 엇갈리지 않았다면 작은 데이터와 큰 데이터 교체
        }
        print(">> 분할 탐색 시작하기 전 : \(array)")
        print()
        print("------------------------------------------------------------")
        print()
        quickSort(&array, start: start, end: right - 1) // 8. 나머지 왼쪽 탐색
        quickSort(&array, start: right + 1, end: end)   // 9. 나머지 오른쪽 탐색
    }
}
quickSort(&array, start: 0, end: array.count - 1)
print(array)
N개의 원소로 이뤄진 두 배열 A, B가 있다. 최대 K번의 바꿔치기 연산을 할 수 있다. 바꿔치기 연산을 수행하여 만들수 있는 배열 A의 원소 합의 최댓값을 구하여라.
입력 조건
1. 첫째줄에는 N, K가 주어진다. (1 ≤ K ≤ N ≤ 100,000)
2. 둘째줄부터 각각 배열 A, B의 원소들이 주어진다. 모든 원소는 10,000,000보다 작은 자연수이다.
입력 예
5 3 1 2 5 4 3 5 5 6 6 5
출력 예
26
글의 복잡성을 줄이기 위해 공통 input과, K번 바꾸기 연산은 첫 글에만 명시했습니다. 궁금하다면 여기를 눌러주세요.
// 퀵 정렬
private func ascendingQuickSort(_ array: inout [Int], start: Int, end: Int) {
    if start >= end { return }
    
    let pivot = start
    var left = start + 1
    var right = end
    
    while left <= right {
        while (left <= end) && (array[left] <= array[pivot]) {
            left += 1
        }
        while (right > start) && (array[right] >= array[pivot]) {
            right -= 1
        }
        if left > right {
            array.swapAt(right, pivot)
        } else {
            array.swapAt(left, right)
        }
        ascendingQuickSort(&array, start: start, end: right - 1)
        ascendingQuickSort(&array, start: right + 1, end: end)
    }
}
private func descendingQuickSort(_ array: inout [Int], start: Int, end: Int) {
    if start >= end { return }
    
    let pivot = start
    var left = start + 1
    var right = end
    
    while left <= right {
        while (left <= end) && (array[left] >= array[pivot]) {
            left += 1
        }
        while (right > start) && (array[right] <= array[pivot]) {
            right -= 1
        }
        if left > right {
            array.swapAt(right, pivot)
        } else {
            array.swapAt(left, right)
        }
        descendingQuickSort(&array, start: start, end: right - 1)
        descendingQuickSort(&array, start: right + 1, end: end)
    }
}
이번엔 그냥 함수자체를 나누어주었다!
이제 마지막 계수 정렬로 넘어가보자..!
🫥 글의 복잡성을 줄이기 위해 공통 input과, K번 바꾸기 연산은 첫 글에만 명시했습니다! 궁금하다면 여기를 눌러주세요.