Computer Science/DS & Algorithm

Divide and Conquer: λΆ„ν•  정볡 - 이뢄탐색, 합병정렬

geum 2021. 4. 16. 15:37

 

κ°œλ…

문제의 μž…λ ₯ 사둀λ₯Ό 두 개 μ΄μƒμ˜ μž‘μ€ μΌ€μ΄μŠ€λ‘œ λΆ„ν• ν•œ ν›„ λΆ„ν• ν•œ μž…λ ₯의 닡을 λ°”λ‘œ ꡬ할 수 μžˆλ‹€λ©΄ μ›λž˜ 문제의 닡은 λΆ„ν• λ‘œ 얻은 닡듀을 톡해 ꡬ할 수 μžˆλŠ” 방식. μƒμœ„ μž…λ ₯ μ‚¬λ‘€μ˜ 해닡을 ν•˜μœ„ μž…λ ₯ 사둀 해닡을 μ΄μš©ν•΄ κ΅¬ν•˜κΈ° λ•Œλ¬Έμ— ν•˜ν–₯식(top-down) 풀이 방식에 μ†ν•œλ‹€.

 

λΆ„ν•  μ •λ³΅μ˜ 흐름

μ˜ˆμ‹œ

1) 이뢄탐색

10 12 15 16 18 20 25 27 42 43

이뢄탐색을 μ‚¬μš©ν•˜λ €λ©΄ 배열이 이미 μ •λ ¬λœ μƒνƒœμ—¬μ•Ό ν•œλ‹€. μœ„μ™€ 같은 λ°°μ—΄μ—μ„œ 27이 λ°°μ—΄ μ•ˆμ— μžˆλŠ”μ§€ ν™•μΈν•œλ‹€κ³  κ°€μ •ν•˜μž.

 

β‘  [λΆ„ν• ] κ°€μš΄λ°μ— μœ„μΉ˜ν•œ μ›μ†Œλ₯Ό κΈ°μ€€μœΌλ‘œ 배열을 λ‚˜λˆ„κ³  μ°ΎλŠ” 값이 κ°€μš΄λ° μ›μ†Œλ³΄λ‹€ μž‘μœΌλ©΄ μ™Όμͺ½ λ°°μ—΄, 크면 였λ₯Έμͺ½ 배열을 선택

β‘‘ [정볡] β‘ μ—μ„œ μ„ νƒν•œ 뢀뢄에 찾고자 ν•˜λŠ” 값이 μžˆλŠ”μ§€ μž¬κ·€μ μœΌλ‘œ 이뢄 검색

β‘’ [병합] β‘‘μ—μ„œ 얻은 λ‹΅μœΌλ‘œ 전체에 λŒ€ν•œ λ‹΅ λ„μΆœ

 

cf. μž¬κ·€λ₯Ό λΆ„ν•  μ •λ³΅μœΌλ‘œ κ΅¬ν˜„ν•  경우 κ³ λ €ν•΄μ•Ό ν•  사항

- λΆ„ν• ν•œ μ‚¬λ‘€μ˜ λ‹΅μœΌλ‘œλΆ€ν„° 전체 μž…λ ₯ μ‚¬λ‘€μ˜ 닡을 κ΅¬ν•˜λŠ” 방법 κ³ μ•ˆν•˜κΈ°

- μ’…λ£Œ 쑰건 μ •ν•˜κΈ°

- μ’…λ£Œ 쑰건을 λ§Œμ‘±ν•  경우 닡을 κ΅¬ν•˜λŠ” 방식 μ •ν•˜κΈ°

 

 

μž¬κ·€λ‘œ κ΅¬ν˜„ν•œ 이뢄탐색(Cμ–Έμ–΄)

int binarySearch(int arr[], int low, int high, int target) {
	// λ°°μ—΄μ˜ 인덱슀 κ°’
	int mid;

	if (low > high) {
		return 0;
	}
	else {
		mid = (low + high) / 2;

		if (arr[mid] == target) {
			return mid;
		}
		else if (arr[mid] < target) {
			return binarySearch(arr, mid + 1, high, target);
		}
		else {
			return binarySearch(arr, low, mid - 1, target);
		}
	}
}

 

 

2) 합병정렬(merge sort)

ν•˜λ‚˜μ˜ 배열을 두 개의 λ°°μ—΄λ‘œ λ‚˜λˆ„μ–΄ μ •λ ¬ μƒνƒœλ₯Ό μœ μ§€ν•˜λ©΄μ„œ 합쳐 μˆœμ„œλŒ€λ‘œ μ •λ ¬λœ ν•œ 개의 μ΅œμ’…μ μΈ 배열을 μ–»λŠ” μ ˆμ°¨μ΄λ‹€. λ°°μ—΄μ˜ 길이가 1이 될 λ•ŒκΉŒμ§€ 뢄할을 λ°˜λ³΅ν•˜λ©°, N개의 μ›μ†Œλ₯Ό 가진 λ°°μ—΄μ˜ 합병정렬 과정은 μ•„λž˜μ™€ κ°™λ‹€.

 

β‘  [λΆ„ν• ] 배열을 반으둜 λΆ„ν• (λΆ„ν• λœ λ°°μ—΄μ˜ μ›μ†ŒλŠ” 각각 N/2개)

β‘‘ [정볡] λΆ„ν• ν•œ 배열을 각각 λ”°λ‘œ μ •λ ¬(λ°°μ—΄μ˜ μ›μ†Œκ°€ 2개 이상이면 합병정렬을 μž¬κ·€ ν˜ΈμΆœν•˜μ—¬ μ •λ ¬)

β‘’ [병합] μ •λ ¬ν•œ 두 배열을 ν•©μΉ˜κΈ°

 

 

합병정렬 κ΅¬ν˜„(Cμ–Έμ–΄)

// μ •λ ¬λœ μƒνƒœμ˜ λΆ€λΆ„ 배열을 ν•©λ³‘ν•˜λŠ” ν•¨μˆ˜
void merge(int array[], int left, int right) {
	int i, j, k;
	int mid = (left + right) / 2;

	i = left;
	j = mid + 1;
	k = left;

	// μ΄μ›ƒν•œ μ›μ†ŒλΌλ¦¬ λΉ„κ΅ν•˜λ©° λ°°μ—΄ μ •λ ¬ 및 μ‚½μž…
	while (i <= mid && j <= right) {
		if (array[i] <= array[j]) {
			res[k] = array[i];
			i++;
		}
		else {
			res[k] = array[j];
			j++;
		}
		k++;
	}

	// λ‚¨μ•„μžˆλŠ” 값듀을 일괄 볡사
	if (i > mid) {
		for (int l = j; l <= right; l++) {
			res[k] = array[l];
			k++;
		}
	}
	else {
		for (int l = i; l <= mid; l++) {
			res[k] = array[l];
			k++;
		}
	}

	// μž„μ‹œ 배열에 λ“€μ–΄μžˆλŠ” 값듀을 μ›λž˜ λ°°μ—΄λ‘œ 볡사
	for (int l = left; l <= right; l++) {
		array[l] = res[l];
	}
}

void mergeSort(int arr[], int l, int r) {
	int mid;

	if (l < r) {
		mid = (l + r) / 2;			// ν•˜λ‚˜μ˜ 배열을 λ‘κ°œλ‘œ κ· λ“± λΆ„ν• 

		mergeSort(arr, l, mid);		// 쀑간 인덱슀 κΈ°μ€€ 쒌츑 λ°°μ—΄
		mergeSort(arr, mid + 1, r);	// 쀑간 인덱슀 κΈ°μ€€ 우츑 λ°°μ—΄

		merge(arr, l, r);			// μ •λ ¬λœ λΆ€λΆ„ 배열듀을 합병
	}
}

 

합병정렬 μ½”λ“œ μ‹€ν–‰ κ²°κ³Ό