์๊ณ ๋ฆฌ์ฆ
1. ์๊ฐ ๋ณต์ก๋
์๊ฐ ๋ณต์ก๋(Time Compexity)
- ์ปดํจํฐ ํ๋ก๊ทธ๋จ์ ์ ๋ ฅ๊ฐ๊ณผ ์ฐ์ฐ ์ํ ์๊ฐ์ ์๊ด๊ด๊ณ
- ํจ์จ์ ์๊ณ ๋ฆฌ์ฆ์ด๋?
- ์ ๋ ฅ๊ฐ์ด ์ปค์ง์ ๋ฐ๋ผ ์ฆ๊ฐํ๋ ์๊ฐ์ ๋น์จ์ ์ต์ํํ ์๊ณ ๋ฆฌ์ฆ
์๊ฐ ๋ณต์ก๋์ ์ข ๋ฅ
O(1): ์์ ์๊ฐ ๋ณต์ก๋
โ ex: ์ธ๋ฑ์ค๋ฅผ ํตํ ์ ๊ทผ
์์ ์ฝ๋
int[] arr = {1, 2, 3, 4, 5};
int x = arr[2]; // retrieves the element at index 2
O(N): ์ ํ ์๊ฐ ๋ณต์ก๋
โ ex: ์ผ๋ฐ์ ์ธ ์ํ ๋ฐ ํ์
์์ ์ฝ๋
int[] arr = {5, 3, 8, 1, 7, 2};
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
System.out.println("Maximum value: " + max);
O(logN): ๋ก๊ทธ ์๊ฐ ๋ณต์ก๋
โ ex: ์ด๋ถํ์
์์ ์ฝ๋
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int target = 5;
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (arr[mid] == target) {
System.out.println("Found at index " + mid);
break;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
O(NlogN): ์ ํ ๋ก๊ทธ ์๊ฐ ๋ณต์ก๋
โ ex: ์ ๋ ฌ (ํต ์ํธ, ๋จธ์ง ์ํธ ๋ฑ)
์์ ์ฝ๋
void quicksort(int[] arr, int left, int right) {
if (left < right) {
int pivotIndex = partition(arr, left, right);
quicksort(arr, left, pivotIndex - 1);
quicksort(arr, pivotIndex + 1, right);
}
}
int partition(int[] arr, int left, int right) {
int pivotValue = arr[right];
int i = left - 1;
for (int j = left; j < right; j++) {
if (arr[j] < pivotValue) {
i++;
swap(arr, i, j);
}
}
swap(arr, i + 1, right);
return i + 1;
}
void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
int[] arr = {5, 3, 8, 1, 7, 2};
quicksort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
O(N^2)
โ ex: ๋ฒ๋ธ ์ํธ, ์ด์ฐจ์ ๋ฐฐ์ด ํ์ ๋ฑ๋ฑ
์์ ์ฝ๋
public static void bubbleSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
boolean swapped = false;
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
if (!swapped) {
break;
}
}
}
O(2^N): ์ง์ ์๊ฐ ๋ณต์ก๋
โ ex: ๋ถ๋ถ์งํฉ ๊ตฌํ๊ธฐ
์์ ์ฝ๋
void generateSubsets(int[] arr) {
int n = arr.length;
int totalSubsets = (int) Math.pow(2, n);
for (int i = 0; i < totalSubsets; i++) {
for (int j = 0; j < n; j++) {
if ((i & (1 << j)) != 0) {
System.out.print(arr[j] + " ");
}
}
System.out.println();
}
}
int[] arr = {1, 2, 3};
generateSubsets(arr);
2. ์ ๋ ฌ
โ ์ค์ cs ์ง๋ฌธ์๋ ๊ฐ ์ ๋ ฌ ๋ฐฉ์์ ๊ฐ๋ ์ ๋ํ ๋น๊ต์ ์๋ ์ฝ๋ ์์ฑ์ด ๋์ฌ ์ ์์ผ๋ ์ ์์๋์!
๋ฒ๋ธ ์ ๋ ฌ (Bubble Sort)
โ ์ธ์ ํ ๋ ์์๋ฅผ ๋น๊ตํ์ฌ ์ ๋ ฌํ๋ ์๊ณ ๋ฆฌ์ฆ
โ ๊ฐ์ฅ ๋จ์ํ๊ณ ์ง๊ด์ ์ด์ง๋ง ์๊ฐ ๋ณต์ก๋๊ฐ O(N^2)
์์ ์ฝ๋
public static void bubbleSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
์ ํ ์ ๋ ฌ (Selection Sort)
โ ์ฃผ์ด์ง ๋ฐฐ์ด์์ ๊ฐ์ฅ ์์ ๊ฐ์ ์ฐพ์์ ์์ผ๋ก ๊ฐ์ง๊ณ ์ค๋ ๊ฒ์ ๋ฐ๋ณตํ์ฌ ์ ๋ ฌํ๋ ์๊ณ ๋ฆฌ์ฆ
โ ์๊ฐ ๋ณต์ก๋: O(N^2)
์์ ์ฝ๋
public static void selectionSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
int minIndex = i;
// ์ฃผ์ด์ง ๋ฐฐ์ด์์ ์ต์๊ฐ ์ฐพ๊ธฐ
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// ์ต์๊ฐ๊ณผ ์์น ๋ฐ๊ฟ์ฃผ๊ธฐ
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}
}
์ฝ์ ์ ๋ ฌ (Insertion Sort)
โ ๋ฐฐ์ด์ ๋ชจ๋ ์์๋ฅผ ์์ ์์๋ค๊ณผ ๋น๊ต ํ์ฌ, ์์ ์ ์์น๋ฅผ ์ฐพ์ ์ฝ์ ํจ์ผ๋ก์จ ์ ๋ ฌ์ ์์ฑํ๋ ์๊ณ ๋ฆฌ์ฆ
โ ์๊ฐ ๋ณต์ก๋: O(N^2)
์์ ์ฝ๋
public static void insertionSort(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; i++) {
int key = target[i];
int j = i - 1;
// ํ๊ฒ์ด ์ด์ ์์๋ณด๋ค ์์ผ๋ฉด ์ด์ ์์๋ฅผ ๋ค๋ก ํ ์นธ์ฉ ๋ฏผ๋ค
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
// ํ๊ฒ์ ์์น์ ๋ง๊ฒ ์ฝ์
ํด์ค๋ค
arr[j + 1] = target;
}
}
ํต ์ ๋ ฌ (Quick Sort)
โ ํน์ ํ ๊ฐ(ํผ๋ฒ)์ ๊ธฐ์ค์ผ๋ก ํฐ ์ซ์์ ์์ ์ซ์๋ฅผ ์๋ก ๊ตํํ ๋ค์ ๋ฐฐ์ด์ ๋ฐ์ผ๋ก ๋ถํ ํ์ฌ ์ ๋ ฌํ๋ ์๊ณ ๋ฆฌ์ฆ
โ ๋ถํ ์ ๋ณต
โ ๋ถ์์ ์ ๋ ฌ
โ O(nlogn) / O(N^2) (์ต์ )
โ ์ต์ ์ธ ๊ฒฝ์ฐ: ์ด๋ฏธ ์ ๋ ฌ๋์ด์๋ ๋ฐฐ์ด, ํผ๋ฒ์ด ์ต๋๊ฐ์ด๋ ์ต์๊ฐ์ผ ๋
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
→ 1์ ํผ๋ฒ์ผ๋ก ์ก๊ณ ์งํํ๋ฉด ๋ชจ๋ ์๋ง๋ค ํผ๋ฒ์ ์ก๊ณ ํ์์ ํ๊ฒ ๋๊ธฐ ๋๋ฌธ์ ์๊ฐ ๋ณต์ก๋๊ฐ O(n^2)๊ฐ ๋๋ค!
์์ ์ฝ๋
// ๋ถํ ์ ๋ณต ํต ์ ๋ ฌ
public static void quickSort(int[] arr, int low, int high) {
if (low < high) {
int pivotIndex = partition(arr, low, high);
quickSort(arr, low, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, high);
}
}
// ํผ๋ฒ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌ
private static int partition(int[] arr, int low, int high) {
// ์ค์ ํผ๋ฒ
int mid = low + (high - low) / 2;
int pivot = arr[mid];
int i = low - 1;
int j = high + 1;
while (true) {
// ํผ๋ฒ๋ณด๋ค ์์ ๊ฐ
do {
i++;
} while (arr[i] < pivot);
// ํผ๋ฒ ๋ณด๋ค ํฐ ๊ฐ
do {
j--;
} while (arr[j] > pivot);
if (i >= j) {
// ์๊ฐ๋ฆฐ ๊ฒฝ์ฐ ํผ๋ฒ ๊ต์ฒด ํ ๋ฐํ
return j;
}
// ํผ๋ฒ ์ผ์ชฝ์๋ ์์ ๊ฐ์ด, ์ค๋ฅธ์ชฝ์๋ ํฐ ๊ฐ์ด ์์นํ๊ฒ ๋๋ค
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
๋ณํฉ ์ ๋ ฌ (Merge Sort)
์ถ์ฒ: ํ์ด์ฌ ์๊ณ ๋ฆฌ์ฆ ์ธํฐ๋ทฐ
โ ์์ ๊ฐ์๊ฐ 0์ด๋ 1์ด ๋ ๋๊น์ง ๊ฐ์ ์ชผ๊ฐ ๋ค ๋ณํฉํ๋ฉด์ ์ ๋ ฌํ๋ ๋ฐฉ๋ฒ
โ ์๊ฐ๋ณต์ก๋: O(logN)
โ ์์ ์ ๋ ฌ
โ ์์ ๋ฐฐ์ด์ ์ํ ์ถ๊ฐ ๊ณต๊ฐ ๋ณต์ก๋
์์ ์ฝ๋
// ๋ถํ ์ ๋ณต์ผ๋ก ๋ณํฉ์ ๋ ฌ ์ํ
public static void mergeSort(int[] arr, int low, int high) {
if (low < high) {
int mid = low + (high - low) / 2;
mergeSort(arr, low, mid);
mergeSort(arr, mid + 1, high);
merge(arr, low, mid, high);
}
}
private static void merge(int[] arr, int low, int mid, int high) {
// ๋ฐฐ์ด ๋ถํ
int n1 = mid - low + 1;
int n2 = high - mid;
int[] leftArr = new int[n1];
int[] rightArr = new int[n2];
for (int i = 0; i < n1; i++) {
leftArr[i] = arr[low + i];
}
for (int j = 0; j < n2; j++) {
rightArr[j] = arr[mid + j + 1];
}
int i = 0;
int j = 0;
int k = low;
// ๋ถํ ํ ๋ฐฐ์ด ์ ๋ ฌ
while (i < n1 && j < n2) {
if (leftArr[i] <= rightArr[j]) {
arr[k] = leftArr[i];
i++;
} else {
arr[k] = rightArr[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = leftArr[i];
i++;
k++;
}
while (j < n2) {
arr[k] = rightArr[j];
j++;
k++;
}
}
๊ฐ ์ ๋ ฌ์ ์๊ฐ ๋ณต์ก๋
3. ์ฌ๊ท
โ ํจ์ ๋ด๋ถ์์ ํจ์๊ฐ ์๊ธฐ ์์ ์ ๋ ๋ค์ ํธ์ถํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์๊ณ ๋ฆฌ์ฆ
โ ๋ฐํ / ์ค๋จ ์กฐ๊ฑด์ ์ ์ค์ ํ๋ ๊ฒ์ด ์ค์ํ๋ค!
์์ ์ฝ๋ (ํฉํ ๋ฆฌ์ผ / ํผ๋ณด๋์น)
// ํฉํ ๋ฆฌ์ผ
public static int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
// ํผ๋ณด๋์น
public static int fibonacci(int n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
4. Dynamic Programming
โ ์์ ๋ถ๋ถ ๋ฌธ์ ๋ค์ ํด๋ฅผ ๊ตฌํ๊ณ ์ด๋ฅผ ์ด์ฉํ์ฌ ๋ณด๋ค ํฐ ํฌ๊ธฐ์ ๋ถ๋ถ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด ๋๊ฐ๋ฉฐ ์ต์ข ์ ์ผ๋ก ์๋ ์ฃผ์ด์ง ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์๊ณ ๋ฆฌ์ฆ
โ DP์ ๋ ๊ฐ์ง ์กฐ๊ฑด
- ์ต์ ๋ถ๋ถ ๊ตฌ์กฐ (Optimal Substructure)
- ํฐ ๋ฌธ์ ๋ฅผ ์์ ๋ฌธ์ ๋ก ๋๋ ์ ์์ผ๋ฉฐ ์์ ๋ฌธ์ ์ ๋ต์ ๋ชจ์์ ํฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์
- ์ค๋ณต๋๋ ๋ถ๋ถ ๋ฌธ์ (Overlapping Subproblem)
- ๋์ผํ ์์ ๋ฌธ์ ๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ํด๊ฒฐํด์ผํจ
โ ๋ฉ๋ชจ์ด์ ์ด์ (Memoization)
- ํ ๋ฒ ๊ณ์ฐํ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ๋ฉ๋ชจํ๋ ๊ธฐ๋ฒ
- ๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ ์ค ํ๋
- ๊ฐ์ ๋ฌธ์ ๋ฅผ ๋ค์ ํธ์ถํ๋ฉด ๋ฉ๋ชจํ๋ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋๋ก ๊ฐ์ ธ์ด
- ๊ฐ์ ๊ธฐ๋กํด ๋๋๋ค๋ ์ ์์ ์บ์ฑ(Caching)์ด๋ผ๊ณ ๋ ํจ
์์ ์ฝ๋ (ํผ๋ณด๋์น)
public static int dpFibonacci(int n) {
if (n <= 1) {
return n;
}
int[] fib = new int[n+1];
fib[0] = 0;
fib[1] = 1;
for (int i = 2; i <= n; i++) {
fib[i] = fib[i-1] + fib[i-2];
}
return fib[n];
}
์์ ์ฝ๋ (0/1 knapsack)
// N: ๊ฐ๋ฐฉ ํฌ๊ธฐ, K: ๋ฌด๊ฒ
static int knapsack(int N, int K, int[] volume, int[] price){
dp = new int[N + 1][K + 1];
for (int i = 0; i <= N; i++) {
for (int j = 0; j <= K; j++) {
if (i == 0 || j == 0) {
dp[i][j] = 0;
} else if (volume[i - 1] <= j) {
dp[i][j] = Math.max(price[i - 1] + dp[i - 1][j - volume[i - 1]], dp[i - 1][j]);
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[N][K];
}
5. ๊ทธ๋ํ ํ์ / ๋ฐฑํธ๋ํน
BFS (Breadth-First Search)
โ ๊ทธ๋ํ์์ ๊ฐ๊น์ด ๋ ธ๋๋ถํฐ ์ฐ์ ์ ์ผ๋ก ํ์
โ ํ(์ ์ ์ ์ถ) ์๋ฃ ๊ตฌ์กฐ ์ฌ์ฉ
โ ํ์ ๊ณผ์
- ํ์ ์์ ๋ ธ๋๋ฅผ ํ์ ์ฝ์ ํ๊ณ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
- ํ์์ ๋ ธ๋๋ฅผ ๊บผ๋ธ ๋ค์ ํด๋น ๋ ธ๋์ ์ธ์ ๋ ธ๋ ์ค์์ ๋ฐฉ๋ฌธํ์ง ์์ ๋ ธ๋๋ฅผ ๋ชจ๋ ํ์ ์ฝ์ ํ๊ณ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌํ๋ค.
- ๋ ์ด์ 2๋ฒ์ ๊ณผ์ ์ ์ํํ ์ ์์ ๋๊น์ง ๋ฐ๋ณตํ๋ค.
โ (๋ชจ๋ ๊ฐ์ ์ ๋น์ฉ์ด ๋์ผํ ๋) ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ๋ ๋ฐ ์ฌ์ฉ
DFS (Depth-First Search)
โ ๊ทธ๋ํ์์ ๊น์ ๋ถ๋ถ์ ์ฐ์ ์ ์ผ๋ก ํ์
โ ์ฌ๊ท / ์คํ(ํ์ ์ ์ถ) ์๋ฃ ๊ตฌ์กฐ ์ฌ์ฉ
โ ํ์ ๊ณผ์
- ํ์ ์์ ๋ ธ๋๋ฅผ ์คํ์ ์ฝ์ ํ๊ณ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
- ์คํ์ ์ต์๋จ ๋ ธ๋์ ๋ฐฉ๋ฌธํ์ง ์์ ์ธ์ ๋ ธ๋๊ฐ ์์ผ๋ฉด ๊ทธ ์ธ์ ๋ ธ๋๋ฅผ ์คํ์ ๋ฃ๊ณ ๋ฐฉ๋ฌธ ์ฒ๋ฆฌ๋ฅผ ํ๋ค. ๋ฐฉ๋ฌธํ์ง ์์ ์ธ์ ๋ ธ๋๊ฐ ์์ผ๋ฉด ์คํ์์ ์ต์๋จ ๋ ธ๋๋ฅผ ๊บผ๋ธ๋ค.
- 2๋ฒ ๊ณผ์ ์ ๋ ์ด์ ์ํํ ์ ์์ ๋๊น์ง ๋ฐ๋ณตํ๋ค.
โ ๋ฐฑํธ๋ํน / ๋ชจ๋ ๊ฒฝ์ฐ๋ฅผ ํ๋ํ๋ ๋ค ํ์ํ๋ ๊ฒฝ์ฐ ์ฃผ๋ก ์ฌ์ฉ
BFS vs DFS
โ ์๊ฐ ๋ณต์ก๋๋ ๋๋ค O(V + E)๋ก ๋์ผ
์ถ์ฒ: ๋ฐํน๋
๋ธ๋ก๊ทธ
์์ ์ฝ๋
import java.util.*;
public class Graph {
private int V;
private LinkedList<Integer>[] adj;
// ๊ทธ๋ํ ๊ตฌํ
public Graph(int v) {
V = v;
adj = new LinkedList[v];
for (int i = 0; i < v; i++) {
adj[i] = new LinkedList<>();
}
}
public void addEdge(int v, int w) {
adj[v].add(w);
}
// BFS (ํ ์ฌ์ฉ)
public void bfs(int s) {
boolean[] visited = new boolean[V];
LinkedList<Integer> queue = new LinkedList<>();
visited[s] = true;
queue.add(s);
while (!queue.isEmpty()) {
s = queue.poll();
System.out.print(s + " ");
Iterator<Integer> i = adj[s].listIterator();
while (i.hasNext()) {
int n = i.next();
if (!visited[n]) {
visited[n] = true;
queue.add(n);
}
}
}
}
// DFS (์ฌ๊ท ์ฌ์ฉ)
public void dfs(int v) {
boolean[] visited = new boolean[V];
dfsUtil(v, visited);
}
private void dfsUtil(int v, boolean[] visited) {
visited[v] = true;
System.out.print(v + " ");
Iterator<Integer> i = adj[v].listIterator();
while (i.hasNext()) {
int n = i.next();
if (!visited[n]) {
dfsUtil(n, visited);
}
}
}
public static void main(String[] args) {
Graph g = new Graph(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
System.out.print("BFS traversal starting from vertex 2: ");
g.bfs(2); // "BFS traversal starting from vertex 2: 2 0 3 1"
System.out.print("\nDFS traversal starting from vertex 2: ");
g.dfs(2); // "DFS traversal starting from vertex 2: 2 0 1 3"
}
}
6. ๊ทธ๋ํ ์ฌํ
๋ฒจ๋งํฌ๋ ์๊ณ ๋ฆฌ์ฆ
โ (๊ฐ์ค์น๊ฐ ์๋ ๊ทธ๋ํ์์) ํ ๋ ธ๋์์ ๋ค๋ฅธ ๋ ธ๋๊น์ง์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ๋ ์๊ณ ๋ฆฌ์ฆ
โ (๋ค์ต์คํธ๋ผ์๋ ๋ค๋ฅด๊ฒ) ๊ฐ์ ์ ๊ฐ์ค์น๊ฐ ์์์ผ ๋๋ ์ฌ์ฉ ๊ฐ๋ฅ
โ ๋ชจ๋ ๊ฐ์ ์ ํ์ํ๋ฉด์ ์ธ์ ํ ์ ์ ์ ๋ํ ์ต๋จ ๊ฑฐ๋ฆฌ ๊ฐฑ์ (Edge relaxation)
โ ์๊ฐ ๋ณต์ก๋: O(VE)
โ ํ์ ๊ณผ์
- ์ถ๋ฐ์ ์์ ๋ชจ๋ ์ ์ ๊น์ง์ ๊ฑฐ๋ฆฌ๋ฅผ ์ ์ฅํ๋ dist[] ๋ฐฐ์ด์ ์ด๊ธฐํํ๋ค. (dist[start] = 0, dist[v] = ๋ฌดํ๋)
- ๊ทธ๋ํ์ ๋ชจ๋ ์ ์ u์ ๋ํด, ๋ค์ ๊ณผ์ ์ V-1๋ฒ ๋ฐ๋ณตํด ์ํํ๋ค:
- ๊ทธ๋ํ์ ๋ชจ๋ ๊ฐ์ (u, v)์ ๋ํด, dist[u] + weight(u, v) < dist[v]์ด๋ฉด, dist[v]๋ฅผ ์๋ก์ด, ๋ ์งง์ ๊ฑฐ๋ฆฌ๋ก ๊ฐฑ์ ํ๋ค.
- ๊ทธ๋ํ์์ ์์ ๊ฐ์ค์น ์ฌ์ดํด์ด ์๋์ง ํ์ธํ๋ค.(์์ ๊ฐ์ค์น ์ฌ์ดํด์ด ์กด์ฌํ ์ ์ ๋๋ก ํ์ํ์ง ๋ชปํ๋ค)
- ์ถ๋ฐ์ ์์ ๋ชจ๋ ์ ์ ๊น์ง์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๋ด๊ณ ์๋ dist[] ๋ฐฐ์ด์ ๋ฐํํฉ๋๋ค.
์์ ์ฝ๋
import java.util.Arrays;
public class BellmanFord {
private int V, E;
private Edge[] edges;
// ๊ทธ๋ํ ์์ฑ์
public BellmanFord(int v, int e) {
V = v;
E = e;
edges = new Edge[e];
}
public void addEdge(int src, int dest, int weight, int i) {
edges[i] = new Edge(src, dest, weight);
}
// ๋ฒจ๋งํฌ๋ ์๊ณ ๋ฆฌ์ฆ
public void bellmanFord(int src) {
// ์ต์ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด ์ด๊ธฐํ
int[] dist = new int[V];
Arrays.fill(dist, Integer.MAX_VALUE);
dist[src] = 0;
// ๋ชจ๋ ์ฃ์ง์ ๋ํด ์ต์๊ฐ ๊ฐฑ์
for (int i = 1; i < V; i++) {
for (int j = 0; j < E; j++) {
int u = edges[j].src;
int v = edges[j].dest;
int weight = edges[j].weight;
if (dist[u] != Integer.MAX_VALUE && dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight;
}
}
}
// ์์ ๊ฐ์ค์น ์ฌ์ดํด ํ์ธ
for (int i = 0; i < E; i++) {
int u = edges[i].src;
int v = edges[i].dest;
int weight = edges[i].weight;
if (dist[u] != Integer.MAX_VALUE && dist[u] + weight < dist[v]) {
System.out.println("Negative weight cycle detected");
return;
}
}
printDistances(src, dist);
}
// ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ
private void printDistances(int src, int[] dist) {
System.out.println("Shortest distances from source vertex " + src + " to all vertices:");
for (int i = 0; i < V; i++) {
System.out.println("Vertex " + i + ": " + dist[i]);
}
}
public static void main(String[] args) {
int V = 5;
int E = 8;
BellmanFord graph = new BellmanFord(V, E);
graph.addEdge(0, 1, -1, 0);
graph.addEdge(0, 2, 4, 1);
graph.addEdge(1, 2, 3, 2);
graph.addEdge(1, 3, 2, 3);
graph.addEdge(1, 4, 2, 4);
graph.addEdge(3, 2, 5, 5);
graph.addEdge(3, 1, 1, 6);
graph.addEdge(4, 3, -3, 7);
int source = 0;
graph.bellmanFord(source);
// Shortest distances from source vertex 0 to all vertices:
// Vertex 0: 0
// Vertex 1: -1
// Vertex 2: 2
// Vertex 3: -2
// Vertex 4: 1
}
}
// ๊ฐ์ ํด๋์ค
class Edge {
int src, dest, weight;
public Edge(int src, int dest, int weight) {
this.src = src;
this.dest = dest;
this.weight = weight;
}
}
๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ
โ ์์ ๊ฐ์ค์น๊ฐ ์๋ ๊ทธ๋ํ์ ํ ์ ์ ์์ ๋ชจ๋ ์ ์ ๊น์ง์ ์ต๋จ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐ๊ฐ ๊ตฌํ๋ ์๊ณ ๋ฆฌ์ฆ
โ ํ์๊ณผ์
- ์ถ๋ฐ์ ์ผ๋ก๋ถํฐ ์ต๋จ๊ฑฐ๋ฆฌ๋ฅผ ์ ์ฅํ ๋ฐฐ์ด distance[v]์ ๋ง๋ค๊ณ ์ถ๋ฐ ๋ ธ๋๋ 0, ๋๋จธ์ง ๋ ธ๋๋ค์ ์ถฉ๋ถํ ํฐ ๊ฐ์ผ๋ก ์ด๊ธฐํ ํ๋ค.
- ํ์ฌ ๋ ธ๋ Current๋ฅผ ์ถ๋ฐ ๋ ธ๋์ ๋ฒํธ๋ก ์ค์ ํ๋ค.
- Current๋ก๋ถํฐ ๊ฐ ์ ์๋ ์์์ ๋ ธ๋ Next์ ๋ํด distance[Current] + P[Current][Next](A๋ฅผ ๊ฑฐ์ณ์ B๋ก ๊ฐ๋ ์ต๋จ๊ฑฐ๋ฆฌ)์ distance[Next](ํ์ฌ๊น์ง ์๋ ค์ง B์ ์ต๋จ ๊ฑฐ๋ฆฌ)์ ๊ฐ์ ๋น๊ตํด์ ์งง์ ๊ฐ(์งง์ ๊ฒฝ๋ก)๋ก ๊ฐฑ์ ํ๋ค.
- Current์ ๋ชจ๋ ์ด์๋ ธ๋ Next์ ๋ํด 3 ์ ์ํํ๋ค.
- Current์ ์ํ๋ฅผ ‘visited=True’๋ก ๋ฐ๊ฟ์ค๋ค. (Current๋ ๋ ์ด์ ์ฌ์ฉํ์ง ์๋๋ค.)
- visited == False์ธ ๋ ธ๋ ์ค ์ถ๋ฐ์ ์ผ๋ก๋ถํฐ ๊ฑฐ๋ฆฌ๊ฐ ๊ฐ์ฅ ์งง์ ๋ ธ๋๋ฅผ Current๋ก ์ค์ ํ๋ค.
- ๋์ฐฉ ๋ ธ๋๊ฐ 'visited == True’๊ฐ ๋๊ฑฐ๋, ๋ ์ด์ ๋ฏธ๋ฐฉ๋ฌธ ๋ ธ๋๋ฅผ ์ ํํ ์ ์์ ๋๊น์ง 3 ~ 6์ ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค
โ ์๊ฐ ๋ณต์ก๋: O(V^2)
โ ์ฐ์ ์์ํ๋ฅผ ์ด์ฉํด ๋ฐ๋ก ๋ค์ ๋ ธ๋์ ๋ํ ์ ๋ณด๋ฅผ ์ถ์ถํด๋ด์ ์ต์ ํ ํ ์ ์๋ค -> ์๊ฐ ๋ณต์ก๋ O(ElogE)
์์ ์ฝ๋
import java.util.*;
public class Dijkstra {
private int V;
private List<Edge>[] adj;
// ๊ทธ๋ํ(์ธ์ ๋ฆฌ์คํธ) ํด๋์ค ์ ์ธ ๋ฐ ์ด๊ธฐํ
public Dijkstra(int v) {
V = v;
adj = new ArrayList[v];
for (int i = 0; i < v; i++) {
adj[i] = new ArrayList<>();
}
}
public void addEdge(int src, int dest, int weight) {
adj[src].add(new Edge(dest, weight));
adj[dest].add(new Edge(src, weight));
}
// ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ (์ฐ์ ์์ํ)
public void dijkstra(int src) {
PriorityQueue<Node> pq = new PriorityQueue<>();
// ์ต๋จ๊ฑฐ๋ฆฌ ํ
์ด๋ธ ์ด๊ธฐํ
int[] dist = new int[V];
Arrays.fill(dist, Integer.MAX_VALUE);
dist[src] = 0;
pq.add(new Node(src, 0));
while (!pq.isEmpty()) {
int u = pq.poll().vertex;
// ์ฐ์ ์์ํ ์ด์ฉํด ์ต๋จ ๊ฑฐ๋ฆฌ ๊ฐฑ์
for (Edge e : adj[u]) {
int v = e.dest;
int weight = e.weight;
if (dist[u] != Integer.MAX_VALUE && dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight;
pq.add(new Node(v, dist[v]));
}
}
}
printDistances(src, dist);
}
// ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ
private void printDistances(int src, int[] dist) {
System.out.println("Shortest distances from source vertex " + src + " to all vertices:");
for (int i = 0; i < V; i++) {
System.out.println("Vertex " + i + ": " + dist[i]);
}
}
public static void main(String[] args) {
int V = 5;
Dijkstra graph = new Dijkstra(V);
graph.addEdge(0, 1, 9);
graph.addEdge(0, 2, 6);
graph.addEdge(0, 3, 5);
graph.addEdge(0, 4, 3);
graph.addEdge(2, 1, 2);
graph.addEdge(2, 3, 4);
int source = 0;
graph.dijkstra(source);
// Shortest distances from source vertex 0 to all vertices:
// Vertex 0: 0
// Vertex 1: 7
// Vertex 2: 6
// Vertex 3: 5
// Vertex 4: 3
}
}
// ์ฃ์ง๋ ๋
ธ๋ ํด๋์ค ์ ์
class Edge {
int dest, weight;
public Edge(int dest, int weight) {
this.dest = dest;
this.weight = weight;
}
}
class Node implements Comparable<Node> {
int vertex, dist;
public Node(int vertex, int dist) {
this.vertex = vertex;
this.dist = dist;
}
public int compareTo(Node other) {
return Integer.compare(dist, other.dist);
}
}
7. ์ต์ ์ ์ฅ ํธ๋ฆฌ (Minimum Spanning Tree)
โ ์ ์ฅํธ๋ฆฌ: ๊ทธ๋ํ ๋ด์ ๋ชจ๋ ์ ์ ์ ํฌํจํ๋ ํธ๋ฆฌ
โ ์ต์ ์ ์ฅํธ๋ฆฌ Spanning Tree ์ค์์ ๊ฐ์ ์ ๊ฐ์ค์น ํฉ์ด ์ต์(Minimun)์ธ ํธ๋ฆฌ
๊ตฌํ: ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ
โ Greedy๋ฅผ ์ด์ฉํด ๊ฐ ๋จ๊ณ์์ ์ฌ์ดํด์ ์ด๋ฃจ์ง ์๋ ์ต์ ๋น์ฉ ๊ฐ์ ์ ์ ํํ๋ค.
โ ํ์ ๊ณผ์
- ๊ฐ์ ์ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํ๋ค. (์ต์ ๋น์ฉ)
- ์ ๋ ฌ๋ ๊ฐ์ ๋ฆฌ์คํธ์์ ์์๋๋ก ์ฌ์ดํด์ ํ์ฑํ์ง ์๋ ๊ฐ์ ์ ์ ํํ๋ค. (์ ๋์จ ํ์ธ๋)
- ์ ํํ ๊ฐ์ ์ ํ์ฌ MST์งํฉ์ ์ถ๊ฐํ๋ค
์์ ์ฝ๋
import java.util.*;
public class KruskalMST {
private int V, E;
private List<Edge> edges;
// ๊ทธ๋ํ ์ ์ธ ๋ฐ ์ด๊ธฐํ
public KruskalMST(int v, int e) {
V = v;
E = e;
edges = new ArrayList<>();
}
public void addEdge(int src, int dest, int weight) {
edges.add(new Edge(src, dest, weight));
}
public int kruskalMST() {
// parent ๋ฐฐ์ด ์ด๊ธฐํ
int cost = 0;
int[] parent = new int[V];
Arrays.fill(parent, -1);
// ์ต์ ์ ์ฅ ํธ๋ฆฌ ๊ฐฑ์
for (Edge e : edges) {
// ์ฌ์ดํด ํ๋ณ
int root1 = find(parent, e.src);
int root2 = find(parent, e.dest);
if (root1 != root2) {
// ๋น์ฉ ๊ณ์ฐ
cost += e.weight;
// ์ ๋์จ
parent[root1] = root2;
}
}
return cost;
}
// ํ์ธ๋ ํจ์(์ฌ์ดํด ํ๋ณ)
private int find(int[] parent, int v) {
if (parent[v] < 0) {
return v;
}
parent[v] = find(parent, parent[v]);
return parent[v];
}
public static void main(String[] args) {
int V = 5;
int E = 7;
KruskalMST graph = new KruskalMST(V, E);
graph.addEdge(0, 1, 2);
graph.addEdge(0, 3, 6);
graph.addEdge(1, 2, 3);
graph.addEdge(1, 3, 8);
graph.addEdge(1, 4, 5);
graph.addEdge(2, 4, 7);
graph.addEdge(3, 4, 9);
int cost = graph.kruskalMST();
System.out.println("Total cost of the Minimum Spanning Tree: " + cost);
// Total cost of the Minimum Spanning Tree: 16
}
}
// ๊ฐ์ ํด๋์ค ์ ์
class Edge implements Comparable<Edge> {
int src, dest, weight;
public Edge(int src, int dest, int weight) {
this.src = src;
this.dest = dest;
this.weight = weight;
}
public int compareTo(Edge other) {
return Integer.compare(weight, other.weight);
}
}
8. ๋ถํ ์ ๋ณต / ์ด๋ถํ์
๋ถํ ์ ๋ณต
โ ๋ฌธ์ ๋ฅผ ๋๋ ์ ์์ ๋๊น์ง ๋๋์ด์ ๊ฐ๊ฐ์ ํ๋ฉด์ ๋ค์ ํฉ๋ณํ์ฌ ๋ฌธ์ ์ ๋ต์ ์ป๋ ์๊ณ ๋ฆฌ์ฆ
โ ์ฃผ๋ก ์ฌ๊ท ํ์ฉ
โ ์์: ๋ณํฉ์ ๋ ฌ, ํต์ ๋ ฌ, ์ด๋ถํ์...
๋ถํ ์ ๋ณต vs DP
โ ๋ถํ ์ ๋ณต์ ๋ถํ ๋ ํ์ ๋ฌธ์ ๊ฐ ๋์ผํ๊ฒ ์ค๋ณต์ด ์ผ์ด๋์ง ์๋ ๊ฒฝ์ฐ์ ์ฐ๋ฉฐ, ๋์ผํ ์ค๋ณต์ด ์ผ์ด๋๋ฉด ๋์ ํ๋ก๊ทธ๋๋ฐ์ ํ์ฉ(๋ฉ๋ชจ์ด์ ์ด์ )
์ด๋ถํ์ (Binary Search)
โ (์ฃผ๋ก ์ ๋ ฌ๋ ๋ฐ์ดํฐ์์) ๊ฒ์ ๋ฒ์๋ฅผ ๋ฐ์ผ๋ก ์ค์ฌ ๋๊ฐ๋ฉด์ ๊ฒ์ ๊ฐ์ ์ฐพ๋ ์๊ณ ๋ฆฌ์ฆ
โ ๋งค๊ฐ๋ณ์ ํ์(Parametric search)์์ ํ์ฉ ๊ฐ๋ฅ!
โ ์๊ฐ ๋ณต์ก๋: O(logN)
์์ ์ฝ๋
public class BinarySearch {
public static int binarySearch(int[] arr, int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
public static void main(String[] args) {
int[] arr = {1, 3, 5, 7, 9};
int target = 7;
int index = binarySearch(arr, target);
if (index == -1) {
System.out.println("Target not found in array");
} else {
System.out.println("Target found at index " + index);
}
}
}
9. ๊ทธ๋ฆฌ๋
โ ์ฌ๋ฌ ๊ฒฝ์ฐ ์ค ํ๋๋ฅผ ๊ฒฐ์ ํด์ผ ํ ๋๋ง๋ค ๊ทธ ์๊ฐ์ ์ต์ ์ด๋ผ๊ณ ์๊ฐ๋๋ ๊ฒ์ ์ ํํด ๋๊ฐ๋ ๋ฐฉ์์ผ๋ก ์งํํ์ฌ ์ต์ข ์ ์ธ ํด๋ต์ ๋๋ฌํ๋ ์๊ณ ๋ฆฌ์ฆ
โ ๊ทธ๋ฆฌ๋์ ๋ ๊ฐ์ง ์กฐ๊ฑด
- ํ์์ค๋ฐ ์ ํ ์กฐ๊ฑด(greedy choice property)๊ณผ
- ์์ ์ ํ์ด ์ดํ์ ์ ํ์ ์ํฅ์ ์ฃผ์ง ์๋๋ค
- ์ต์ ๋ถ๋ถ ๊ตฌ์กฐ ์กฐ๊ฑด(optimal substructure)
- ๋ฌธ์ ์ ๋ํ ์ต์ ํด๊ฐ ๋ถ๋ถ๋ฌธ์ ์ ๋ํด์๋ ์ญ์ ์ต์ ํด์ด๋ค.
์์ ์ฝ๋ (๋ ์)
import java.util.Arrays;
public class FractionalKnapsack {
// ๊ทธ๋ฆฌ๋๋ก ๋ฐฐ๋ญ ์ฑ์๋ฃ๊ธฐ
public static double getMaximumValue(int[] weights, int[] values, int capacity) {
int n = weights.length;
double[] ratios = new double[n]; // ๊ฐ์น/๋ฌด๊ฒ ๋น์จ
// ๋น์จ ๊ตฌํ๊ธฐ
for (int i = 0; i < n; i++) {
ratios[i] = (double) values[i] / weights[i];
}
// ๋ฌผ๊ฑด ์ ๋ณด
Item[] items = new Item[n];
for (int i = 0; i < n; i++) {
items[i] = new Item(weights[i], values[i], ratios[i]);
}
// ์ ๋ ฌ
Arrays.sort(items);
double maximumValue = 0;
// ๊ทธ๋ฆฌ๋ํ๊ฒ ๋ฌผ๊ฑด ์ฑ์ ๋ฃ๊ธฐ
for (int i = n - 1; i >= 0; i--) {
if (capacity == 0) {
break;
}
double weightToAdd = Math.min(items[i].getWeight(), capacity);
maximumValue += weightToAdd * items[i].getRatio();
capacity -= weightToAdd;
}
return maximumValue;
}
public static void main(String[] args) {
int[] weights = {10, 20, 30};
int[] values = {60, 100, 120};
int capacity = 50;
double maximumValue = getMaximumValue(weights, values, capacity);
System.out.println("Maximum value we can obtain = " + maximumValue); // prints "Maximum value we can obtain = 240.0"
}
}
// ํด๋์ค ์ ์
class Item implements Comparable<Item> {
private int weight;
private int value;
private double ratio;
public Item(int weight, int value, double ratio) {
this.weight = weight;
this.value = value;
this.ratio = ratio;
}
public int getWeight() {
return weight;
}
public int getValue() {
return value;
}
public double getRatio() {
return ratio;
}
@Override
public int compareTo(Item item) {
return Double.compare(this.ratio, item.ratio);
}
}
'โญ Personal_Study > CS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
CS ๋ฉด์ ์ง๋ฌธ ์ ๋ฆฌ - ์ด์์ฒด์ 2 (0) | 2023.03.03 |
---|---|
CS ๋ฉด์ ์ง๋ฌธ ์ ๋ฆฌ - ์ด์์ฒด์ 1 (3) | 2023.03.02 |
CS ๋ฉด์ ์ง๋ฌธ ์ ๋ฆฌ - ๋คํธ์ํฌ (0) | 2023.02.23 |
CS ๋ฉด์ ์ง๋ฌธ ์ ๋ฆฌ - ์๋ฃ๊ตฌ์กฐ (0) | 2023.02.12 |
CS ๋ฉด์ ์ง๋ฌธ ์ ๋ฆฌ - ํ๋ก๊ทธ๋๋ฐ ์ผ๋ฐ (0) | 2023.02.06 |
๋๊ธ