You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// 추가 공간을 사용하지 않는 방법 publicstaticStringreverseString(Stringoriginal) {
char[] chs = original.toCharArray();
intlength = chs.length;
for(inti=0; i<length/2; i++) {
// swap characterschartmp = chs[i];
chs[i] = chs[length-1-i];
chs[length-1-i] = tmp;
}
returnnewString(chs);
}
// 추가 공간을 사용 하는 방법publicstaticStringreverseString(Strignoriginal) {
char[] chs = original.toCharArray();
char[] result = newchar[chs.length];
for(inti=0; i<chs.length - 1; i++) {
result[i] = chs[chs.length - i - 1];
}
returnnewString(result);
}
1.2.4 Swap
// 기본 스왑 publicvoidswap(intx, inty) {
inttmp = x;
x = y;
y = tmp;
}
// XOR을 사용한 스왑 // (피연산자의 수가 서로 다를 경우에만 1인 XOR의 성질을 이용해서 2진수로 풀어 계산 해보면 된다.)publicvoidswap(intx, inty) {
x = x ^ y;
y = x ^ y;
x = x ^ y;
}
실행 설명
a. 리스트 가운데서 하나의 원소를 고른다. 이렇게 고른 원소를 피벗이라고 한다.
b. 피벗 앞에는 피벗보다 값이 작은 모든 원소들이 오고, 피벗 뒤에는 피벗보다 값이 큰 모든 원소들이 오도록 피벗을 기준으로 리스트를 둘로 나눈다. 이렇게 리스트를 둘로 나누는 것을 분할이라고 한다. 분할을 마친 뒤에 피벗은 더 이상 움직이지 않는다.
c. 분할된 두 개의 작은 리스트에 대해 재귀(Recursion)적으로 이 과정을 반복한다. 재귀는 리스트의 크기가 0이나 1이 될 때까지 반복된다.
실행 설명
a. 리스트의 길이가 0 또는 1이면 이미 정렬된 것으로 본다. 그렇지 않은 경우에는
b. 정렬되지 않은 리스트를 절반으로 잘라 비슷한 크기의 두 부분 리스트로 나눈다.
c. 각 부분 리스트를 재귀적으로 합병 정렬을 이용해 정렬한다.
d. 두 부분 리스트를 다시 하나의 정렬된 리스트로 합병한다.
publicclassMergesort {
privateint[] numbers;
privateint[] helper;
privateintnumber;
publicvoidsort(int[] values) {
this.numbers = values;
number = values.length;
this.helper = newint[number];
mergesort(0, number - 1);
}
privatevoidmergesort(intlow, inthigh) {
// check if low is smaller then high, if not then the array is sortedif (low < high) {
// Get the index of the element which is in the middleintmiddle = low + (high - low) / 2;
// Sort the left side of the arraymergesort(low, middle);
// Sort the right side of the arraymergesort(middle + 1, high);
// Combine them bothmerge(low, middle, high);
}
}
privatevoidmerge(intlow, intmiddle, inthigh) {
// Copy both parts into the helper arrayfor (inti = low; i <= high; i++) {
helper[i] = numbers[i];
}
inti = low;
intj = middle + 1;
intk = low;
// Copy the smallest values from either the left or the right side back// to the original arraywhile (i <= middle && j <= high) {
if (helper[i] <= helper[j]) {
numbers[k] = helper[i];
i++;
} else {
numbers[k] = helper[j];
j++;
}
k++;
}
// Copy the rest of the left side of the array into the target arraywhile (i <= middle) {
numbers[k] = helper[i];
k++;
i++;
}
}
}
3. 탐색
3.1 BFS (너비 우선 탐색)
너비 우선 탐색(Breadth-first search, BFS)은 맹목적 탐색방법의 하나로 시작 정점을 방문한 후 시작 정점에 인접한 모든 정점들을 우선 방문하는 방법이다. 더 이상 방문하지 않은 정점이 없을 때까지 방문하지 않은 모든 정점들에 대해서도 넓이 우선 검색을 적용한다. OPEN List 는 큐를 사용해야만 레벨 순서대로 접근이 가능하다.
장점
출발노드에서 목표노드까지의 최단 길이 경로를 보장한다.
단점
경로가 매우 길 경우에는 탐색 가지가 급격히 증가함에 따라 보다 많은 기억 공간을 필요로 하게 된다.
해가 존재하지 않는다면 유한 그래프(finite graph)의 경우에는 모든 그래프를 탐색한 후에 실패로 끝난다.
무한 그래프(infinite graph)의 경우에는 결코 해를 찾지도 못하고, 끝내지도 못한다.
맹목적 탐색방법의 하나로 탐색트리의 최근에 첨가된 노드를 선택하고, 이 노드에 적용 가능한 동작자 중 하나를 적용하여 트리에 다음 수준(level)의 한 개의 자식노드를 첨가하며, 첨가된 자식 노드가 목표노드일 때까지 앞의 자식 노드의 첨가 과정을 반복해 가는 방식이다.
장점
단지 현 경로상의 노드들만을 기억하면 되므로 저장공간의 수요가 비교적 적다.
목표노드가 깊은 단계에 있을 경우 해를 빨리 구할 수 있다.
단점
해가 없는 경로에 깊이 빠질 가능성이 있다. 따라서 실제의 경우 미리 지정한 임의의 깊이까지만 탐색하고 목표노드를 발견하지 못하면 다음의 경로를 따라 탐색하는 방법이 유용할 수 있다.
얻어진 해가 최단 경로가 된다는 보장이 없다. 이는 목표에 이르는 경로가 다수인 문제에 대해 깊이우선 탐색은 해에 다다르면 탐색을 끝내버리므로, 이때 얻어진 해는 최적이 아닐 수 있다는 의미이다.