정렬 (Sorting)

🔍 개요

  • 전제 조건 : 반드시 정렬 된 상태여야 함
  • 시간 복잡도 : O(log N)

📚 기본 로직

int binarySearch(int[] arr, int target) {
	int left = 0;
	int right = arr.length - 1;
	
	while(left <= right) {
		int mid = (left + right) / 2;
		if(arr[mid] == target) {
			return mid; // 찾음
		} else if(arr[mid] < target) {
			left = mid + 1;
		} else {
			right = mid - 1;
		}
	}
	return -1; // 못 찾음
}

⚡️ 응용 패턴

(A) Lower Bound & Upper Bound

  • Lower Bound : target 이상이 처음 나오는 위치
  • Upper Bound : target 초과가 처음 나오는 위치
// Arrays.binarySearch는 정확히 같은 값만 찾음 -> 보통 직접 구현
int lowerBound(int[] arr, int target) {
	int left = 0;
	int right = arr.length;
	
	while(left <= right) {
		int mid = (left + right) / 2;
		if(arr[mid] >= target) {
			right = mid;
		} else {
			left = mid + 1;
		}
	}
	return left;
}
 
int upperBound(int[] arr, int target) {
	int left = 0;
	int right = arr.length;
	
	while(left <= right) {
		int mid = (left + right) / 2;
		if(arr[mid] > target) {
			right = mid;
		} else {
			left = mid + 1;
		}
	}
	return left;
}
  • 아이디어 : “조건을 만족하는 값 중 가장 작은/큰 것”을 찾는 방식
  • 형태
    • while (left <= right) 형태로 범위 좁혀감
    • mid 값으로 조건 검사 조건 만족하면 범위 줄이기

(예시 : 랜선 자르기 문제)

long binarySearch(long[] arr, long target) {
	long left = 1;
	long right = Arrays.stream(arr).max().getAsLong();
	long ans = 0;
	
	while(left <= right) {
		long mid = (left + right) / 2;
		long count = 0;
		for(long x : arr) {
			count += (x / mid);
		}
		
		if(count >= target) { // 조건 만족 -> 더 크게 자를 수 있는지 확인
			ans = mid;
			left = mid + 1;
		} else {
			right = mid - 1;
		}
	}
	return ans;
}