퀵선택 알고리즘은 특정 위치의 원소를 찾는 데 사용되는 효율적인 분할 정복 알고리즘 중 하나이다.
퀵정렬 알고리즘 일부를 이용하여 전체를 정렬하지 않고 특정 위치의 원소를 찾을 수 있다.
이 알고리즘의 평균 시간 복잡도는 O(n)이며, 최악의 경우에 O(n^2)이 될 수 있다.
동작 순서
- 피벗 선택: 배열에서 피벗을 선택한다. 일반적으로 배열의 가운데 원소를 선택한다.
- 분할: 피벗을 기준으로 배열을 두 그룹으로 나눈다. 작은 원소는 피벗 왼쪽에 위치하고, 큰 원소는 오른쪽에 위치한다.
- 쿼리 위치 확인: 찾고자 하는 원소의 위치를 확인한다. 이 위치가 현재 피벗의 위치와 일치하면 찾은 것이다.
- 재귀적으로 반복: 찾고자 하는 위치가 피벗의 위치보다 작으면 왼쪽 부분 배열에서 반복적으로 알고리즘을 수행한다. 반대로 크면 오른쪽 부분 배열에서 반복한다.
public class QuickSelect {
/**
* 배열에서 주어진 순서에 해당하는 요소를 선택하는 메서드
* @param arr 배열
* @param order 순서 (1부터 시작)
* @return 선택된 요소
*/
public static int quickSelect(int[] arr, int order) {
return quickSelect(arr, 0, arr.length - 1, order - 1);
}
/**
* 배열에서 주어진 범위 내에서 주어진 순서에 해당하는 요소를 선택하는 재귀 메서드
* @param arr 배열
* @param start 범위의 시작 인덱스
* @param end 범위의 끝 인덱스
* @param order 순서
* @return 선택된 요소
*/
private static int quickSelect(int[] arr, int start, int end, int order) {
if (start > end) {
return -1;
}
int pivotIndex = partition(arr, start, end);
if (pivotIndex == order) {
return arr[pivotIndex];
} else if (pivotIndex < order) {
return quickSelect(arr, pivotIndex + 1, end, order);
} else {
return quickSelect(arr, start, pivotIndex - 1, order);
}
}
/**
* 배열의 특정 범위를 피벗을 기준으로 분할하는 메서드
* @param arr 배열
* @param start 범위의 시작 인덱스
* @param end 범위의 끝 인덱스
* @return 피벗의 인덱스
*/
private static int partition(int[] arr, int start, int end) {
int middle = (start + end) / 2;
int pivot = arr[middle];
// pivot을 start 위치로 옮기기
swap(arr, start, middle);
int leftPointer = start + 1;
int rightPointer = end;
while (leftPointer <= rightPointer) {
while (leftPointer <= rightPointer && arr[leftPointer] < pivot) {
leftPointer++;
}
while (leftPointer <= rightPointer && arr[rightPointer] > pivot) {
rightPointer--;
}
if (leftPointer <= rightPointer) {
swap(arr, leftPointer, rightPointer);
leftPointer++;
rightPointer--;
}
}
// rightPointer 오른쪽으로는 pivot보다 큰 수들만 존재한다.
swap(arr, start, rightPointer);
// rightPointer의 위치에 pivot이 들어간다.
return rightPointer;
}
/**
* 배열의 두 요소를 교환하는 메서드
* @param arr 배열
* @param i 교환할 요소의 인덱스
* @param j 교환할 요소의 인덱스
*/
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[
728x90
'자료구조 & 알고리즘' 카테고리의 다른 글
다익스트라 알고리즘 (0) | 2024.02.16 |
---|---|
위상 정렬 알고리즘 (0) | 2024.02.16 |
유니온-파인드 알고리즘 (0) | 2024.02.05 |
단순 선택 정렬, 단순 삽입 정렬, 이진 삽입 정렬 (0) | 2023.12.12 |
버블 정렬, 칵테일 정렬 (0) | 2023.12.11 |